当我尝试将派生类对象分配给基类时,派生类中的“唯一”部分将被分割。那么被切掉的那部分会发生什么呢?它们是否被正确销毁,或者只是丢失了内存?而且,如果我在那些派生部分上分配了一些内存,那么当对象切片发生时,分配的内存是否会被正确释放?我想这会导致一些不确定的行为,因为我们在对象切片时从未声明过销毁那些衍生零件的方法。
毕竟,使用对象切片需要什么情况?还是我们应该始终避免这种情况?
答案 0 :(得分:-1)
对象切片通常在将派生类对象复制到基类对象中时发生。因此,基类对象具有切片后剩下的所有数据。基础对象中的另一部分丢失。为避免这种情况,您可以使用指针或对象的引用作为函数参数传递,因为任何类型的指针或引用都占用相同的内存量。或者,可以通过禁止对象创建,使基类函数在其中纯虚拟,从而防止对象切片。无法创建包含纯虚方法的类的对象。
#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; }
};
// 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;
}
我们可以通过使用指针或引用来避免上述意外行为。当对象的指针或引用作为函数参数传递时,不会发生对象切片,因为任何类型的指针或引用都占用相同的内存量。例如,如果将上面程序中的全局方法myfunc()更改为following,则不会发生对象切片。
// rest of code is similar to above
void somefunc (Base &obj)
{
obj.display();
}
// rest of code is similar to above
如果使用指针并将程序更改为following,则会得到相同的输出。
// 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;
}