一、將派生類對象賦值給基類對象?
注意:這不同於將派生類對象賦值給基類的引用或者指針
請看如下代碼:
Base b; //基類對象
Derived d; //派生類對象
b=d; //賦值
這將使用哪一個運算符呢?賦值語句實際上會被轉換爲下面的語句:
b.operator=(d);
其中左邊的對象是基類對象,所以調用的是基類中的賦值運算符重載函數,右邊的對象作爲傳入的參數。而實參與形參結合的過程實際上就是派生類對象賦值給基類對象的引用。所以,b=d
實際上就是將d
中的基類成員賦值給了b
,而忽略了d
中新增加的成員。總之,派生類對象可以賦值給基類對象,但是隻涉及到基類中的成員。
二、將基類對象賦值給派生類對象?
Base b; //基類對象
Derived d; //派生類對象
d=b; //賦值
賦值語句會被轉換爲下面的語句:
d.operator=(b);
左邊的對象是派生類對象,所以會調用派生類中的賦值運算符重載函數,右邊的對象會作爲實參傳入。但是C++中基類對象不能自動的轉換爲派生類對象的引用,因此這樣的代碼是不能運行的。那麼我們應該怎樣解決這樣的問題呢?
解決辦法一:
在派生類中定義一個轉換構造函數(這個之前我已經寫過一篇關於它的博客),如下:
Derived(const Base& ba)
該轉換構造函數可以將Base
類型轉換爲Derived
。當我們定義了一個如此的轉換構造函數之後,當實參與形參結合時,發現實參是一個Base
類型與形參不符,此時因爲類中有相應的轉換構造函數,所以此時就會調用該函數,程序就會用b
去構造一個臨時的
Derived
對象,然後再用該臨時對象作爲賦值運算符的實參。
解決辦法二:
在派生類中以基類對象作爲形參再新定義一個賦值運算符重載函數,如下:
Derived& operator=(const Base& ba); //此時的形參是基類的引用
這樣賦值運算符的類型相匹配,無需進行其他操作。
總而言之,問題”基類對象能否賦值給派生類對象”的答案是可能可以。只有有上面所述的兩個解決辦法中的任意一個時,就可以進行賦值,否則是不可以的。