2017-05-29 8 views
1

私はC++でC#setterに似た何かを実装しようとしています。アイデアは、クラスのプロパティと対応するセッターの列挙を持つことです。私のコードは次のようになります。実装をクラス定義に記述します。関数ポインタへの静的マップ

#include <string> 
#include <map> 

enum ClassProperties 
{ 
    Id, Name 
}; 

class MyClass 
{ 
public: 
    int Id; 
    std::string Name; 

    public void SetValue(ClassProperties c, std::string value){ 
      setters[c](this, value); 

    } 

private: 
    typedef void (* t_setter)(MyClass *, std::string); 

    static void set_id(MyClass * obj, std::string value) { 
     obj->Id = std::stoi(value); 
    } 
    static void set_name(MyClass * obj, std::string value) { 
     obj->Name = value; 
    } 

    static std::map<ClassProperties, t_setter> setters = {{ClassProperties:: Id, set_id}, {ClassProperties::Name, set_name}}; 


}; 

私が間違って何をやっている私は、このコードはcooresponding機能を選択し、それを呼び出すことを期待したいが、私は

error: in-class initialization of static data member ‘std::map<ClassProperties, void (**)(MyClass*, std::basic_string<char>)> MyClass::setters’ of incomplete type 

error: could not convert ‘{{Id, MyClass::set_id}, {Name, MyClass::set_name}}’ from ‘<brace-enclosed initializer list>’ to ‘std::map<ClassProperties, void (**)(MyClass*, std::basic_string<char>)>’ 

最後の行にエラーを取得しますか?

+1

打ち鳴らすは++より直接的与える:あなたはこの作業を持っているたら – aschepler

+0

「エラー非const静的データメンバは、ラインの外に初期化されなければならない」、あなたは「メンバ関数へのポインタ」に見たいと思うかもしれません、したがって、 'set_id'と' set_name'を非静的関数にすることができ、 'obj.set_id(value);'として呼び出すことができます –

+0

BTW。これはC#setterのようには見えません。 –

答えて

2

settersの初期化が間違っています。

1)クラス本体から行を削除します:あなたは次のように変更する必要があり

static std::map<ClassProperties, t_setter> setters = 
    {{ClassProperties:: Id, set_id}, {ClassProperties::Name, set_name}}; 

2)クラス本体のうち、静的メンバの適切な初期化を追加します。

std::map<ClassProperties, MyClass::t_setter> MyClass::setters = { 
     { ClassProperties::Id, &MyClass::set_id }, 
     { ClassProperties::Name, &MyClass::set_name } 
}; 

ほかSetValue機能の前に、公開指定子を削除する必要があります。

wandbox example

+0

大変ありがとうございますが、今度は 'MyClass :: setters''の多重定義 – Vahagn

+0

@Vahagn私はwandboxの例を追加しました。 –

+0

@Vahagnあなたは大歓迎です:) –

関連する問題