はじめに
Effective C++ 第3版の6項32ページから勉強していきます。
今回は、前回に引き続き「コンパイラによるコピーコンストラクタの自動生成の禁止」についです。
Effective C++ 第3版 - 6項 コンパイラが自動生成することを望まない関数は使用を禁止しよう -
コンパイラによるコピーコンストラクタの自動生成の禁止(2)
前回の復習と前置き
前回の投稿で、オブジェクト(クラス)をコピーするようなコードがあれば、コンパイルできないように、する書き方について勉強しました。
その結果、privateでコピーコンストラクタ・コピー代入演算子の宣言だけし、定義を書かないことで、メンバ関数からの呼び出しを防ぐという結論にいたりました。
今回は、コピーコンストラクタとコピー代入演算子をprivateに宣言したクラスを作り、それをHomeForSaleの基底クラスとすることで、オブジェクトをコピーするようなコードがあれば、コンパイルできないようにする書き方について勉強していきます。
今回の勉強内容
コピーを禁止するためだけに定義するこのクラスをUncopyableとして、クラスを作成していきます。
下にUncopyableというクラスを示します。
class Uncopyable {
protected:
Uncopyable() {} //宣言と定義
~Uncopyable() {} //宣言と定義
private:
Uncopyable(const Uncopyable&); // 宣言のみ
Uncopyable& operator=(const Uncopyable&); // 宣言のみ
};
上のように、コンストラクタ・デストラクタは、宣言と定義を行い。
コピーコンストラクタとコピー代入演算子は、宣言のみ行います。
そして、下のコードのように宣言すると、HomeForSaleクラスをコピーすることをできなくします。
class HomeForSale : private Uncopyable {
public:
explicit HomeForSale(const std::string& city, const int& value) {
city_ = city;
value_ = value;
}
private:
std::string city_;
int value_;
};
上のように定義したHomeForSaleでは、メンバ関数やフレンド関数であっても、コピーを行おうとすると、
コンパイラがコピーコンストラクタやコピー代入演算子を生成しようとして、そこでエラーとなります。
以下に、勉強で使用したコードを示します。
サンプルコード
# include <iostream>
class Uncopyable {
protected:
Uncopyable() {} //宣言と定義
~Uncopyable() {} //宣言と定義
private:
Uncopyable(const Uncopyable&); // 宣言のみ
Uncopyable& operator=(const Uncopyable&); // 宣言のみ
};
class HomeForSale : private Uncopyable {
public:
explicit HomeForSale(const std::string& city, const int& value) {
city_ = city;
value_ = value;
}
private:
std::string city_;
int value_;
};
int main(int argc, char* argv[]) {
std::cout << "6_no_copy_constract2.cpp" << std::endl;
HomeForSale h1("Tokyo", 2);
HomeForSale h2("Osaka", 3);
// HomeForSale h3(h1); // コンパイルエラー
// h1 = h2; // コンパイルエラー
}
実行結果
まとめ
今回は、コピーコンストラクタとコピー代入演算子をprivateに宣言したクラスを作り、それをHomeForSaleの基底クラスとすることで、オブジェクトをコピーするようなコードがあれば、コンパイルできないようにする書き方について勉強しました。
Uncopyableの継承がpublicでなかったり、デストラクタが仮想でなかったりとよく分からないこともありましたが、今後勉強していきたいと思います。
また、前回の投稿のコメントでC++11以降であれば、
HomeForSale(const HomeForSale&) = delete;
と書くことで、自動生成を抑止することができると教えていただいたので、こっちを使おうと思います。
## 参考文献
[1] https://www.amazon.co.jp/gp/product/4621066099/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0