1. 程式人生 > >C++類中一個建構函式呼叫另一個建構函式

C++類中一個建構函式呼叫另一個建構函式

class A
{
	int a;
	int b;
	int c;
public:
	A(int aa, int bb) : a(aa), b(bb),c(0)  { cout << "aa bb" << endl; }
	A(int aa, int bb, int cc);
};

上面類中,已經有一個建構函式,形參有兩個,我們又過載一個有3個形參的建構函式,為了減少程式碼量,就想著讓3個引數的建構函式呼叫2個引數的建構函式,然後在執行一些自己的程式碼,這就如同派生類先呼叫基類的同名函式,在執行自己特有的程式碼。這種機制如何實現呢?

做法一:在3個引數中顯示呼叫2個引數的建構函式(這肯定是可以的, 建構函式是類的成員函式),此時要用到placement new技術。

3引數建構函式可以這樣實現:

	A::A(int aa, int bb, int cc) 
	{
		new (this) A(aa, bb);
		...
	}
建構函式有2個執行階段:1)是在初始化列表的初始化階段;2)在建構函式體內的賦值階段。上述方法是在第二個階段。placement new技術的形式是 new(void *p) Type(...),表示在p所指的記憶體區域呼叫Type建構函式,該過程沒有記憶體請求。上述實現有“投機取巧”之嫌,就是在物件地址處,呼叫2個引數的建構函式重新生成一個新的物件然後覆蓋該物件。

做法二:在VS2013中發現可以在建構函式初始化列表直接呼叫,類似於呼叫基類建構函式。該方法在g++中不適合。

	A::A(int aa, int bb, int cc) :A(aa, bb)
	{
		...
	}
上述說了建構函式有2個執行階段,該方法是在第一個階段進行的,這種方式有點類似C#裡面的機制,更加方便。該方法有個注意事項是不能在A(aa, bb)後面在接c(cc)了,因為呼叫2個引數的建構函式之後,就相當於該物件已經初始化完成了,不能在初始化列表放入其他成員的初始化形式。只能放在建構函式體中的賦值階段。該方法目前只能用在VS2013中。

做法二有很大的侷限性,不過確實很方便。不知標準文件對於建構函式互相呼叫有怎樣的規定?是否以後其他編譯器會加入該功能?