木曜日, 3月 15, 2007

[続]C++でプロパティ

以前参考にしようと思っていた件です。

試しにこんなコードを書いて使ってみていたのですが、 template<typename O, typename T> class Property { O* owner; T (O::*get)(void) const; void (O::*set)(const T&); public: Property(O* _owner, T(O::*_get)(void) const, void (O::*_set)(const T&)) : owner(_owner), get(_get), set(_set) {} operator T() const { return (owner->*get)(); } void operator=(const T& value) { (owner->*set)(value); } };こんなコード class A { int a; void set(const int& _x) { a = _x; } int get() const { return a; } public: Property<A,int> x; A() : x(this,&A::get,&A::set) {} };を書いてみると A a,b; a.x = 1; b.x = a.x; // → "b.x = 1" a.x = 2; // → "b.x = 2" !!という世にも恐ろしい結果が! (((( ;゚Д゚))))

しばらく悩んで、浅はかにも「コンパイラのバグ?」なんて思ったりもしたのですが、よく考えると"b.x = a.x;"の所で(いやここしか考えられないのですが)デフォルトコピーコンストラクタがメンバ変数全部(母屋へのポインタ)をコピーしていた所為 orz

こんな感じに Property(const Property<O,T>& p) : owner(p._owner), get(p._get), set(p._set) {} void operator=(const T& value) { (owner->*set)(value); } void operator=(const Property<O,T>& p) { (owner->*set)(p.value()); }コードを書き足しすと…ちゃんと期待通りの動作をするようになりました。 ( ´∀`)

…単にねこさんの修行が足りてないだけなのですが orz

0 件のコメント: