1. 程式人生 > >【初級】C++中子類物件轉型為父類物件時,編譯器默默做了什麼?

【初級】C++中子類物件轉型為父類物件時,編譯器默默做了什麼?

被問及C++中將子類物件轉型為父類物件時,會發生什麼?大部分人可能會回答說:子類成份會被"閹割",也就是說它不再具有子類特性。確實是這樣,不過我想知道編譯器是怎麼處理“閹割”的。請看如下程式碼,

Child chd;

Base b0(chd);
Base b1 = chd;

Base b2;
b2 = chd;

很明顯,b0和b1都是通過呼叫Base的拷貝建構函式來完成構建的。對於b2,編譯器首先呼叫Base的預設建構函式進行構造,然後呼叫Base的賦值運算子來把子類中的父類成份賦值給b2。

再來看看下面的程式碼:

class Base
{
public:
	 Base() 
	 {
		i = 0;
		printf("Base()\n");
	 }
	 
	 Base(const Base & base) : i(base.i)
	 {
		printf("Base copy.\n");
	 }
	 
	 Base& operator=(const Base &base)
	 {
		printf("Assignment.\n");
		return *this;
	 }
	 
	 void Inc() {++i;}
	 void print() {printf("%d\n",i);}
	 
	 int i;
};

class Child : public Base
{
	
};

int main()
{
	Child chd;
	chd.Inc(); // add 1
	
	Base base(chd); // copy
	base.print(); 

        static_cast<Base>(chd).Inc();
	chd.print(); // 打印出1	

	((Base)chd).Inc();
	chd.print(); // 打印出1	
	return 0;
}


 很明顯,main()函式中的第一個列印語句會輸出1,為什麼第二,三個也輸出1,不是對i作加1操作了嗎。原來上面的static_cast<Base>(chd).Inc()或者 ((Base)chd).Inc()會被編譯器轉化為如下程式碼:

Base temp(chd);
temp.Inc();

是的,編譯器通過拷貝建構函式構造出一個臨時的Base物件,然後對那個臨時物件進行加1操作,所以並沒有改變chd物件的狀態。

總結:編譯器“閹割”子類物件是通過拷貝建構函式或賦值運算子來完成的。注意轉型中臨時物件可能產生。