C++继承(5) - 对象切割

来源:互联网 发布:电子书转换格式软件 编辑:程序博客网 时间:2024/06/03 21:14

1.对象切割的场景

C++中,一个子类对象可以直接赋值给一个基类对象,但是反之则不行。
如下例子所示:

class Base { int x, y; }; class Derived : public Base {int z, w; }; int main(){    Derived d;    Base b = d;// 会发生对象切割,d中的z和w成员会丢失。}
对象切割发生在一个子类对象赋值给基类对象时,子类自有的数据成员会在基类的对象中被切割/丢失掉。
#include <iostream>using namespace std; class Base{protected:    int i;public:    Base(int a)     { i = a; }    virtual void display()    { cout <<"I am Base class object, i = " << i << endl; }}; class Derived : public Base{    int j;public:    Derived(int a, int b) : Base(a) { j = b; }    virtual void display()    { cout <<"I am Derived class object, i = "           << i <<", j = " << j << endl;  }}; // 全局函数.按值传递参数.void somefunc (Base obj){    obj.display();} int main(){    Base b(33);    Derived d(45, 54);    somefunc(b);    somefunc(d); // 发生对象切割,对象d中的成员j被丢失    return 0;}
输出:
I am Base class object, i = 33
I am Base class object, i = 45

2.对象切割的避免方法

我们可以使用指针或者引用来避免这个问题. 当使用指针或者引用来传递函数参数时,则不会发生对象切割这个问题。因为对于任何类型来说,指针都是占用相同内存大小的。

例如,如果把上面程序中的全局函数somefunc() 修改为下面代码,则不会产生对象切割问题。

void somefunc(Base &obj){    obj.display();}
输出:
I am Base class object, i = 33
I am Derived class object, i = 45, j = 54

同样,如果使用指针,也能得到同样的结果:

void somefunc(Base *objp){    objp->display();} int main(){    Base *bp =new Base(33) ;    Derived *dp =new Derived(45, 54);    somefunc(bp);    somefunc(dp); // 不会产生对象切割问题    return 0;}
输出:
I am Base class object, i = 33
I am Derived class object, i = 45, j = 54

另外,也可以使用将基类成员函数定义为纯虚函数的方法,来避免对象切割问题。因为虚基类是不能生成对象的。

0 0