noncopyableはレベル3警告C4511,C4512を生み出す
あるクラスのコピーや代入を禁じたいときに、皆さんはどうしているでしょうか?こういうのは代入演算子等を間違って書いてしまった時にコンパイラエラーではじいて欲しいものですよね。てなわけで、良くあるのがコピーコンストラクタと代入演算子をprivateに置くという方法です。
class ClassA { private: // 実装しないでしかもprivateにおいておく ClassA( const ClassA& obj ); ClassA& operator=( const ClassA& obj ); };
ただ、これを毎回書くのが面倒ですよね、そういうときにboost::noncopyableの出番です。noncopyableは下のようなシンプルなクラスで、これから継承するだけでコピー禁止の機能が実装できます。
class noncopyable { protected: noncopyable() {} ~noncopyable() {} private: // emphasize the following members are private noncopyable( const noncopyable& ); const noncopyable& operator=( const noncopyable& ); };
つまり、下のようにClassAを定義することでコピー禁止となるわけです。
class ClassA : public boost::noncopyable { };
と、ここまでは良かったのですが、このClassAから継承してさらにClassBを定義してみます。
class ClassB : public ClassA { };
すると、コンパイラが次のようなレベル3警告を出してくるのです…。
warning C4511: 'ClassB' : コピー コンストラクタを生成することができません。 : 'ClassB' の宣言を確認してください。 warning C4512: 'ClassB' : 代入演算子を生成できません。 : 'ClassB' の宣言を確認してください。
不思議なのは、この警告ってClassAにも出てしかるべきなんですよね。だってnoncopyableクラスの中で既にコピーコンストラクタも代入演算子もprivateなんですから。なぜ2回継承すると警告が出るのでしょうか。
まあ出てしまうものはしかたないんで、わざわざClassBの前後を
#pragma warning( disable : 4511) #pragma warning( disable : 4512) class ClassB : public ClassA { }; #pragma warning( default : 4511) #pragma warning( default : 4512)
でくくってます…これって最初よりもタイプ量が多いです(;つД`);なにか使い方間違ってるのかな、うーむ。どなたか知っている人教えてください…。