C++建構函式初始化順序

hellogiser的部落格發表於2014-09-28



1.建構函式、解構函式與拷貝建構函式介紹
建構函式
  • 建構函式不能有返回值
  • 預設建構函式時,系統將自動呼叫該預設建構函式初始化物件,預設建構函式會將所有資料成員都初始化為零或空
  • 建立一個物件時,系統自動呼叫建構函式
解構函式
  • 解構函式沒有引數,也沒有返回值。不能過載,也就是說,一個類中只可能定義一個解構函式
  • 如果一個類中沒有定義解構函式,系統也會自動生成一個預設的解構函式,為空函式,什麼都不做
  • 呼叫條件:1.在函式體內定義的物件,當函式執行結束時,該物件所在類的解構函式會被自動呼叫;2.用new運算子動態構建的物件,在使用delete運算子釋放它時。
拷貝建構函式
拷貝建構函式實際上也是建構函式,具有一般建構函式的所有特性,其名字也與所屬類名相同。拷貝建構函式中只有一個引數,這個引數是對某個同類物件的引用。它在三種情況下被呼叫:
  • 用類的一個已知的物件去初始化該類的另一個物件時;
  • 函式的形參是類的物件,呼叫函式進行形參和實參的結合時;
  • 函式的返回值是類的物件,函式執行完返回撥用者。
【程式碼】
/*
version: 1.0
author: hellogiser
blog: http://www.cnblogs.com/hellogiser
date: 2014/9/27
*/
#include ”stdafx.h”
#include <iostream>
using namespace std;
class OBJ1
{
public:
OBJ1()
{
cout << ”OBJ1\n”;
}
};
class OBJ2
{
public:
OBJ2()
{
cout << ”OBJ2\n”;
}
};
class Base1
{
public:
Base1()
{
cout << ”Base1\n”;
}
};
class Base2
{
public:
Base2()
{
cout << ”Base2\n”;
}
};
class Base3
{
public:
Base3()
{
cout << ”Base3\n”;
}
};
class Base4
{
public:
Base4()
{
cout << ”Base4\n”;
}
};
class Derived : public Base1, virtual public Base2,
public Base3, virtual public Base4
{
public:
Derived() : Base4(), Base3(), Base2(),
Base1(), obj2(), obj1()
{
cout << ”Derived.\n”;
}
protected:
OBJ1 obj1;
OBJ2 obj2;
};
void test()
{
Derived aa;
cout << ”This is ok.\n”;
}
int main()
{
test();
return 0;
}
/*
Base2
Base4
Base1
Base3
OBJ1
OBJ2
Derived.
This is ok.
*/
【程式碼2】
/*
version: 1.0
author: hellogiser
blog: http://www.cnblogs.com/hellogiser
date: 2014/9/27
*/
#include ”stdafx.h”
#include <iostream>
using namespace std;
class Base1
{
public:
Base1(int i)
{
cout << ”Base1 ” << i << endl;
}
};
class Base2
{
public:
Base2(int i)
{
cout << ”Base2 ” << i << endl;
}
};
class Base3
{
public:
Base3()
{
cout << ”Base3 *” << endl;
}
};
class Derived : public Base2,  public Base1, virtual public Base3
{
public:
Derived(int a, int b, int c, int d, int e)
: Base1(a), b2(d), b1(c), Base2(b)
{
m = e;
cout << ”Derived.\n”;
}
protected:
Base1 b1;
Base2 b2;
Base3 b3;
int m;
};
void test()
{
Derived aa(1, 2, 3, 4, 5);
cout << ”This is ok.\n”;
}
int main()
{
test();
return 0;
}
/*
Base3 *
Base2 2
Base1 1
Base1 3
Base2 4
Base3 *
Derived.
This is ok.
*/
分析:
(1) virtual

按照繼承順序:Base3

第一步:先繼承Base3,在初始化列表裡找不到Base3(), 則呼叫Base3裡的預設建構函式Base3(),列印”Base3  *”

(2)non-virtual

按照繼承順序:Base2,Base1

第二步:繼承Base2,在初始化列表中找Base2(b),呼叫Base2的建構函式Base2(2),列印”Base2 2″

第三步:繼承Base1,在初始化列表中找Base1(a),呼叫Base1的建構函式Base1(1),列印”Base1 1″

(3)data member

按照申明順序:b1,b2,b3

第四步:構造b1,在初始化列表中找b1(c),呼叫Base1的建構函式Base1(3),列印”Base1 3″

第五步:構造b2,在初始化列表中找b2(d),呼叫Base2的建構函式Base1(4),列印”Base2 4″

第六步:構造b3,在初始化列表中找不到b3(),呼叫Base3的建構函式Base3(),列印”Base3 *”

(4)self

第7步:執行自己的建構函式體,輸出”Derived.”

原文來自:hellogiser的部落格
評論(1)

相關文章