Help us understand the problem. What is going on with this article?

勉強記録 18日目 〜コンパイラが自動で生成する関数〜 - Effective C++ 第3版 -

 はじめに

Effective C++ 第3版の5項27ページから勉強していきます。
今回は、「コンパイラが自動で生成する関数」についです。

Effective C++ 第3版 - 5項 C++が自動で書き、自動で呼び出す関数を知ろう -

コンパイラが自動で生成する関数

クラスにおけるコンパイラが自動で生成する関数

クラス内で、コピーコンストラクタ、コピー代入演算子、デストラクタを宣言しなけらば、コンパイラが自動でそれらを生成することになっています。
また、コンストラクタを1つも宣言しなければ、コンパイラは自動でデフォルトコンストラクタを生成することになっています。

つまり、

class ClassA{};

と書いても、それは、本質的には、次のように書いたものと同じになります。

class ClassA {
 public:
  ClassA(){};                              // デフォルトコンストラクタ
  ClassA(const ClassA& rhs){};             // コピーコンストラクタ
  ~ClassA(){};                             // デストラクタ
  ClassA& operator=(const ClassA& rhs){};  // コピー代入演算子
};

ただし、上で書いたような関数は、必要なときにだけ生成されることになっています。
生成が必要なのは、以下のようなコードを書いた時です。

class ClassA {};

ClassA ca1;       // デフォルトコンストラクタとデストラクタを生成が必要
ClassA ca2(ca1);  // コピーコンストラクタの生成が必要
ca2 = ca1;        // コピー代入演算子の生成が必要

コンパイラが生成してくれる関数はどのように機能するのか?

コンパイラが生成してくれるデフォルトコンストラクタとデストラクタは、それぞれ、基底クラスや非staticなデータメンバのコンストラクタとデストラクタを(見えないところで)で呼び出してくれます。

また、関数の仮想性は継承されるため、基底クラスが仮想デストラクタを持てば、派生クラスにコンパイラが生成するデストラクタも仮想となります。

しかし、基底クラスのデストラクタが仮想でない場合、コンストラクタが生成するデストラクタは、仮想にはなりません。(文献[1]より引用)

これは、どういう意味だろう?
コンストラクタが生成するデストラクタとは??

コンパイラが自動で生成するコピーコンストラクタとコピー代入演算子は、コピー元の非staticなデータメンバを、コピー先のオブジェクトに、単純にコピーするだけです。

以下のようなクラスで例を説明します

template<typename T>
class ClassB {
 public:
  explicit ClassB(const std::string& name, const T& value) {
    name_ = name;
    value_ = value;
  };

 private:
  std::string name_;
  T           value_;
};

ClassBは、コンストラクタが明示的に宣言されているので、コンパイラはデフォルトコンストラクタを生成しません。
これは、重要です。
つまり、「引数を取るコンストラクタ」を持つようクラスを設計した場合、コンパイラが安易に「引数を取らないコンストラクタ」を生成し、設計をだいなしにしてしまう、などということはない。

ClassB<int> cb1; // NG

ClassBは、コピーコンストラクタもコピー代入演算子も宣言されていません。
そのため、(必要な場合は)コンパイラが生成します。
以下のように、コピーコンストラクタを呼び出してみます。

ClassB<int> cb1("First", 1);
ClassB<int> cb2(cb1);  // コピーコンストラクタの呼び出し

コンパイラが生成するコピーコンストラクタによって、cb2.name_ と cb2.value_ が初期化されます。
その際、それぞれ cb1.name_ と cb1.value_ の値が使われます。

以下に、勉強で使用したコードを示します。

サンプルコード

#include <iostream>

class ClassA {};

/*
class ClassA {
 public:
  ClassA(){};                              // デフォルトコンストラクタ
  ClassA(const ClassA& rhs){};             // コピーコンストラクタ
  ~ClassA(){};                             // デストラクタ
  ClassA& operator=(const ClassA& rhs){};  // コピー代入演算子
};*/

template <typename T>
class ClassB {
 public:
  explicit ClassB(const std::string& name, const T& value) {
    name_  = name;
    value_ = value;
  };
  std::string getName() { return name_; };
  T           getValue() { return value_; };

 private:
  std::string name_;
  T           value_;
};

int main(int argc, char* argv[]) {
  std::cout << "5_class.cpp" << std::endl;
  ClassA ca1;       // デフォルトコンストラクタとデストラクタを生成が必要
  ClassA ca2(ca1);  // コピーコンストラクタの生成が必要
  ca2 = ca1;        // コピー代入演算子の生成が必要
  // ClassB<int> cb1;
  ClassB<int> cb1("First", 1);
  ClassB<int> cb2(cb1);  // コピーコンストラクタの呼び出し
  std::cout << "##### cb1   ##### " << std::endl;
  std::cout << "name : " << cb1.getName() << " , value : " << cb1.getValue() << std::endl;


  std::cout << "##### cb2   ##### " << std::endl;
  std::cout << "name : " << cb2.getName() << " , value : " << cb2.getValue() << std::endl;
}

実行結果

5_class.png

参考文献

[1] https://www.amazon.co.jp/gp/product/4621066099/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした