C++コンストラクタ初期化順序

2860 ワード

コンストラクション関数の初期化は次の順序で行います.
1.まず、仮想ベースクラスを構築し、任意の仮想ベースクラスの構築関数を継承された順序で構築する.
2.次に非仮想ベースクラスを構築し、任意の非仮想ベースクラスの構築関数を継承された順序で構築する.
3.次に、メンバー・オブジェクトを構築し、任意のメンバー・オブジェクトの構築関数を宣言された順序で呼び出す.
4.最後にクラス自身の構造関数を呼び出す.
構造関数は脳なしで構造関数を順番に反転すればよい.
次に簡単だが全面的な例を挙げて理解を助ける.
#include 

using namespace std;

class OBJ1
{
public:
	OBJ1() { cout << "OBJ1" << endl; }
	~OBJ1() {	cout << "OBJ1 destory" << endl;}
};

class OBJ2
{
public:
	OBJ2() { cout << "OBJ2
"; } ~OBJ2(){cout << "OBJ2 destory" <

出力結果は以下の通りです.
Base2
Base4
Base1
Base3
OBJ1
OBJ2
Derived
----------------------
construct ok
----------------------
Derived destory
OBJ2 destory
OBJ1 destory
Base3 destory
Base1 destory
Base4 destory
Base2 destory

プログラムでは、Derivedは4つのベースクラスに継承され、Base 2とBase 4は仮想ベースクラスであり、Base 2はBase 4より前に継承されるので、順番にBase 2が先に構築される.
仮想ベースクラスの構築が完了し、非仮想ベースクラスBase 1とBase 3が構築され、同様に順番に構築され、Base 1はBase 3の前にある.
ベースクラスの構築が完了し、メンバーオブジェクトobj 1とobj 2が構築され、同じ理屈で順序に従います.最後にクラス自己構築関数を呼び出し、Derivedを出力します.
解析関数の順序はまったく逆で、説明する必要はありません.
もちろん、多重継承の問題にも遭遇します.まず、ベースクラスのコンストラクション関数を呼び出します.ベースクラスのコンストラクション関数にベースクラスがまだ存在する場合、プログラムは最初のベースクラスが初期化されるまで上を検索し続けます.
言うのは難しいかもしれませんが、同じように栗を挙げましょう.
#include
using namespace std;
class Base
{
public:
	Base() { std::cout << "Base::Base()" << std::endl; }
	~Base() { std::cout << "Base::~Base()" << std::endl; }
};

class Base1 :public Base
{
public:
	Base1() { std::cout << "Base1::Base1()" << std::endl; }
	~Base1() { std::cout << "Base1::~Base1()" << std::endl; }
};

class Derive
{
public:
	Derive() { std::cout << "Derive::Derive()" << std::endl; }
	~Derive() { std::cout << "Derive::~Derive()" << std::endl; }
};

class Derive1 :public Base1
{
private:
	Derive m_derive;
public:
	Derive1() { std::cout << "Derive1::Derive1()" << std::endl; }
	~Derive1() { std::cout << "Derive1::~Derive1()" << std::endl; }
};

int main()
{
	Derive1 derive;
	return 0;
}

出力結果は以下の通りです.
Base::Base()
Base1::Base1()
Derive::Derive()
Derive1::Derive1()
Derive1::~Derive1()
Derive::~Derive()
Base1::~Base1()
Base::~Base()

この例では、Derivel 1はBase 1から継承され、Base 1はBaseから継承されるので、順番に構築するとBase、Base 1、そしてDerive 1となる.一方、Derive 1にはメンバーオブジェクトDeriveがあるので、Derive 1のコンストラクション関数を呼び出す前に、Deriveを構築する必要があります(最初の3点を参照).
以上の2つの例を通して,C++構造関数の初期化順序について一定の理解が得られたに違いない.(コミカル)