當把乙個派生類物件賦給乙個基類物件時,會發生物件切割。(另外用基類物件強制轉換派生類物件也會)
物件切割會發生什麼呢?
#include "stdafx.h"
#include
using namespace std;
class cshape
~cshape(){}
virtual void draw()
double m_color;
};class crect: public cshape
~crect(){};
double size()
virtual void draw()
double m_width;
double m_height;
};int main(int argc, char* argv)
輸出結果為:
this is a shape!
1this is a shape!
1this is a shape!
1this is a rect!
1this is a rect!
1請按任意鍵繼續……
shp=rect;會呼叫 cshape的預設賦值函式,shp的cshape屬性值與rect相同,但其虛函式表指標指向基類cshape虛函式表。
((cshape)rect).draw();會呼叫cshape預設的拷貝建構函式,生成乙個中間變數,其虛函式表指標指向基類cshape虛函式表。
多型的實現是通過指標和引用;而物件的轉換只會造成物件切割,不能實現多型。
注意下面兩句的不同
*pshape=rect;//物件切割
pshape=▭//多型
附基類和派生類物件間賦值的問題:
class a
class b:public a
a a_object;
b b_object;
(1)a_boject=b_object;
(2)b_object=a_boject;
有關以上兩句的說明:
(1)a_boject=b_object;呼叫default a::operator =,由編譯器自動生成,它的函式宣告大致類似於:a operator = (a rhs),反正=號右邊要求是乙個a的物件,bobject作為a的子類物件亦是可行的,只不過傳遞過程中會產生「截斷」。
(2)b_object=a_boject;呼叫default b::operator =,也由編譯器自動生成,它的函式宣告大致類似於:b operator = (b rhs),這裡=號右邊要求是乙個b的物件,aobject這時就不可行了。(編譯器將報錯)
這時,單單過載b::operator =也無濟於事,因為你無法改變operator =函式引數必須是b物件的這個事實。要實現b_object=a_boject;可以過載強制型別轉換函式,也可以利用編譯器隱式型別轉換的能力,如:
class a
};class b:public a
b(a a){}//必須有
};a aobject;
b bobject;
int main()
小結:class 物件作引數時,用reference to const替換pass by value可避免物件切割。
基類指標與派生類指標的相互轉換
1,直接用基類指標引用基類物件
2,直接用派生類指標引用派生類物件
3,用基類指標引用乙個派生類物件,由於派生類物件也是基類的物件,所以這種引用是安全的,
但是只能引用基類成員。若試圖通過基類指標引用那些只在派生類中才有的成員,編譯器會報告語法錯誤。(解決該問題的答案是虛函式和多型性)
4,用派生類指標引用基類的物件。這種引用方式會導致語法錯誤。派生類指標必須先強制轉換為基類指標,這種方法是安全的。
而在侯捷的深入淺出mfc中第二章c++重要性質中:
1、如果你以乙個"基類之指標"指向乙個"派生類之物件",那麼經由該指標你只能呼叫該基類所定義的函式
2、如果你以乙個「派生類之指標」指向乙個「基類之物件」,你必須先做明顯的轉型操作(explicit cast),這種作法很危險。
3、如果基類和派生類都定義了「相同名稱之函式」,那麼通過物件指標呼叫成員函式時,到底呼叫了那個函式,必須視該指標的原始型別而定,而不是視指標實際所指的物件的型別而定,這與第1點其實意義相通。
#include
#include
using namespace std;
class a
基類代表著最少的確定的資訊,而派生類則代表著較多的確定的資訊。
乙個基類的指標可以指向乙個派生類的物件,意味著乙個指標可以指向乙個容納了多於自己期望的資訊量的物件。那麼當這樣的乙個操作發生後,這個指標就可以做出一些額外的操作,這些操作是它在被定義的時候並沒有期望能夠做到的,或者說並沒有想到的。
與此相對的是,乙個派生類的指標則不能指向乙個基類的物件。因為如果可以這樣做的話,那麼這個派生類的指標在被定義的時候所期望能做的所有事情中將有一部分不再能夠做到,因為在它指向的那個基類的物件中根本就沒有提供那些在派生類派生的時候新增加的方法。但是c++則保證乙個指標定義之後,它至少要能夠做和它被期望做的一樣多的事情。那麼,派生類指標指向基類物件的意圖當然不能被允許。
附一段比較有趣的**:
// virtual function.cpp : 定義控制台應用程式的入口點。
#include "stdafx.h"
#include
using namespace std;
class ihello
;class iworld
;class helloworld: public ihello,public iworld
;void helloworld::hello1()
C 之物件切割
from 華山大師兄 問題描述 程式如下 include include using namespace std class base class derived public base void fun1 base b void fun2 base b void fun3 base b intma...
c 物件切割 Object Slicing
當把乙個派生類物件賦給乙個基類物件時,會發生物件切割。另外用基類物件強制轉換派生類物件也會 物件切割會發生什麼呢?include using namespace std class cshape cshape virtual void draw double m color class crect ...
c 物件切割示例
概念 當乙個子類物件通過值傳遞給基類物件,如foo base derived obj 這個基類的拷貝建構函式將被呼叫.此時子類的特性將被切割,只有基類相關操作.也就是說如果我們向上轉型如果不用引用或指標,物件將被切割.這是也我們應該傳引用而不是傳值的原因.示例 cpp include include...