天天看點

c++對象切割(Object Slicing)

當把一個派生類對象賦給一個基類對象時,會發生對象切割。(另外用基類對象強制轉換派生類對象也會)

對象切割會發生什麼呢?

#include <iostream>

using namespace std;

class CShape

{

public:

          CShape ()

          {

                      m_color=0;

          }

          ~CShape(){}

          virtual void draw()

          {

                      cout<<"This is a shape!"<<endl;

                      cout<<m_color<<endl;

          }          

          double m_color;

};

class CRect: public CShape

{

public:

          CRect()

          {

                      m_width=5;

                      m_height=4;

                      m_color=1;

          }

          ~CRect(){};       

          double size()

          {

                      return m_width*m_height;

          }

          virtual void draw()

          {

                      cout<<"This is a rect!"<<endl;

                      cout<<m_color<<endl;

          }

          double m_width;

          double   m_height;

};

int main(int argc, char* argv[])

{

          CShape shp;

          CRect rect;

    shp = rect;

    shp.draw();

          ((CShape)rect).draw();//注意此行

          CShape *pShape=new CShape();

          *pShape=rect;//對象切割

          pShape->draw();

          pShape=&rect;//多态實作,

          pShape->draw();

          return 0;

}

shp=rect; 會調用 CShape的預設指派函數,shp的CShape屬性值與rect相同,但其虛函數表指針指向基類CShape虛函數表。

((CShape)rect).draw(); 會調用CShape預設的拷貝構造函數,生成一個中間變量,其虛函數表指針指向基類CShape虛函數表。

多态的實作是通過指針和引用;而對象的轉換隻會造成對象切割,不能實作多态。

注意下面兩句的不同

*pShape=rect;//對象切割

pShape=&rect;//多态

附基類和派生類對象間指派的問題:

class A

{

}

Class B:public A

{

}

A a_object;

B b_object;

有關

(1)a_boject=b_object;

(2)b_object=a_boject;

的說明。

==============

(1)aobject=bobject; 調用default A::operator =,由編譯器自動生成,它的函數聲明大緻類似于:A operator = (A rhs),反正=号右邊要求是一個A的對象,bobject作為A的子類對象亦是可行的,隻不過傳遞過程中會産生“截斷”。

(2)bobject=aobject; 調用default B::operator =,也由編譯器自動生成,它的函數聲明大緻類似于:B operator = (B rhs),這裡=号右邊要求是一個B的對象,aobject這時就不可行了。(編譯器将報錯)

這時,單單重載B::operator =也無濟于事,因為你無法改變operator = 函數參數必須是B對象的這個事實。要實作bobject=aobject;可以重載強制類型轉換函數,也可以利用編譯器隐式類型轉換的能力,如:

class A

{

public:

A(){}

};

class B:public A

{

public:

B(){}

B(A a){}//必須有

};

A aobject;

B bobject;

int main()

{

a_object=b_object;

b_object=a_object;

return 0;

}

--------------------------------------

Class 對象作參數時,用reference to const替換pass by value可避免對象切割。