📜  C++中的对象切片

📅  最后修改于: 2021-05-30 15:14:58             🧑  作者: Mango

在C++中,可以将派生类对象分配给基类对象,但是另一种方法是不可能的。

class Base { int x, y; };
  
class Derived : public Base { int z, w; };
  
int main() 
{
    Derived d;
    Base b = d; // Object Slicing,  z and w of d are sliced off
}

对象派生发生在将派生类对象分配给基类对象时,派生类对象的其他属性被切分以形成基类对象。

#include 
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;  }
};
  
// Global method, Base class object is passed by value
void somefunc (Base obj)
{
    obj.display();
}
  
int main()
{
    Base b(33);
    Derived d(45, 54);
    somefunc(b);
    somefunc(d);  // Object Slicing, the member j of d is sliced off
    return 0;
}

输出:

I am Base class object, i = 33
I am Base class object, i = 45

我们可以通过使用指针或引用来避免上述意外行为。当对象的指针或引用作为函数参数传递时,不会发生对象切片,因为任何类型的指针或引用都占用相同的内存量。例如,如果我们将上面程序中的全局方法myfunc()更改为following,则不会发生对象切片。

// rest of code is similar to above
void somefunc (Base &obj)
{
    obj.display();
}           
// rest of code is similar to above

输出:

I am Base class object, i = 33
I am Derived class object, i = 45, j = 54

如果使用指针并将程序更改为以下代码,则将获得相同的输出。

// rest of code is similar to above
void somefunc (Base *objp)
{
    objp->display();
}
  
int main()
{
    Base *bp = new Base(33) ;
    Derived *dp = new Derived(45, 54);
    somefunc(bp);
    somefunc(dp);  // No Object Slicing
    return 0;
}

输出:

I am Base class object, i = 33
I am Derived class object, i = 45, j = 54

通过禁止对象创建使基类函数纯虚拟,可以防止对象切片。无法创建包含纯虚方法的类的对象。

要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”