C++継承用noncopyableクラスの実装

1622 ワード

C++11でクラスのコピー動作を禁止するには、対応する関数をdeleteに設定するだけでよいので、標準ライブラリのstd::unique_ptrを参照してください.
unique_ptr (const unique_ptr&) = delete;
unique_ptr& operator= (const unique_ptr&) = delete;

従来の規格では、対応する関数をprivate関数としていた.
ただし、通常のクラスでは、クラスのメンバー関数宣言を表示しないと、クラスがコピーできないタイプかどうかはわかりません.C++では,継承の技法を用いてnoncopyableクラスを簡単に実現できる.
class NonCopyable {
protected:
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable& operator=(const NonCopyable&) = delete;

    NonCopyable() = default;
    ~NonCopyable() = default;
};

このクラスを継承するだけで派生クラスがコピーできないことを保証できます.
class A : public NonCopyable {};

int main() {
    A a1;
    A a2 = a1;  //     
    A a3;
    a3 = a1;  //     
    return 0;
}

ここで利用するのはC++の合成コンストラクタで、派生クラスがデフォルトのコンストラクタ/解析関数/コピーコンストラクタ/賦値演算子を呼び出すと、まずベースクラスのデフォルトのコンストラクタ/解析関数/コピーコンストラクタ/賦値演算子を呼び出すが、ベースクラスではコピーコンストラクタと賦値演算子が使用できないため、派生クラスはコピー動作を行うことができない.同時に、NonCopyableクラスにデフォルトのコンストラクタ/コンストラクタを宣言し、派生クラスでベースクラス(NonCopyable)の対応する関数を呼び出してベースクラス部分をコンストラクタ/コンストラクタできるようにします.
もちろん,必要であれば派生クラスはコピー構造関数と付与演算子を定義することも可能であるが,この行為は許容されるが,論理的に矛盾し,プログラマーのミスである.
class A : private NonCopyable {
public:
    A(int i) : i_(i) {}
    A(const A& rhs) : i_(rhs.i_) {}
    A& operator=(const A& rhs) { i_ = rhs.i_; return *this; }

    void show() { cout << i_ << endl;}
private:
    int i_;
};

int main() {
    A a1(3);
    A a2 = a1;  // OK
    a2 = a1;  // OK
    a2.show();
    return 0;
}

参照boost::noncopyableの実装