在c++中,什么是对象切片,什么时候发生?
当前回答
切片问题很严重,因为它会导致内存损坏,而且很难保证程序不会受到这种问题的困扰。要用语言设计它,支持继承的类应该只能通过引用(而不是通过值)访问。D编程语言具有此属性。
考虑从A派生的类A和类B。如果A部分有一个指针p,而B实例指向B的附加数据,则可能发生内存损坏。然后,当附加数据被切片时,p指向垃圾。
其他回答
当派生类对象被分配给基类对象时,派生类对象的其他属性将从基类对象中切下(丢弃)。
class Base {
int x;
};
class Derived : public Base {
int z;
};
int main()
{
Derived d;
Base b = d; // Object Slicing, z of d is sliced off
}
切片问题很严重,因为它会导致内存损坏,而且很难保证程序不会受到这种问题的困扰。要用语言设计它,支持继承的类应该只能通过引用(而不是通过值)访问。D编程语言具有此属性。
考虑从A派生的类A和类B。如果A部分有一个指针p,而B实例指向B的附加数据,则可能发生内存损坏。然后,当附加数据被切片时,p指向垃圾。
1.切片问题的定义
如果D是基类B的派生类,则可以将派生类型的对象分配给base类型的变量(或参数)。
例子
class Pet
{
public:
string name;
};
class Dog : public Pet
{
public:
string breed;
};
int main()
{
Dog dog;
Pet pet;
dog.name = "Tommy";
dog.breed = "Kangal Dog";
pet = dog;
cout << pet.breed; //ERROR
尽管上面的赋值是允许的,但赋值给变量宠物的值将丢失其品种字段。这被称为切片问题。
2.如何解决切片问题
为了解决这个问题,我们使用指向动态变量的指针。
例子
Pet *ptrP;
Dog *ptrD;
ptrD = new Dog;
ptrD->name = "Tommy";
ptrD->breed = "Kangal Dog";
ptrP = ptrD;
cout << ((Dog *)ptrP)->breed;
在这种情况下,没有动态变量的数据成员或成员函数被ptrD(后代类对象)指向的对象将丢失。此外,如果需要使用函数,则函数必须是虚拟函数。
在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
}
当派生类对象分配给基类对象时,对象切片发生,派生类对象的其他属性被切片以形成基类对象。
好的,在阅读了许多解释对象切片的文章后,我会尝试一下,但不知道它是如何变得有问题的。
可能导致内存损坏的恶性场景如下:
类在多态基类上提供(意外地,可能是编译器生成的)赋值。客户端复制并切片派生类的实例。客户端调用一个虚拟成员函数,该函数访问切片状态。