在c++中,什么是对象切片,什么时候发生?
当前回答
如果您有一个基类a和一个派生类B,那么您可以执行以下操作。
void wantAnA(A myA)
{
// work with myA
}
B derived;
// work with the object "derived"
wantAnA(derived);
现在,方法wantAnA需要派生的副本。然而,派生的对象不能完全复制,因为类B可以创建不在其基类A中的其他成员变量。
因此,要调用wantAnA,编译器将“切片”派生类的所有其他成员。结果可能是您不想创建的对象,因为
它可能是不完整的,它的行为类似于A对象(B类的所有特殊行为都丢失了)。
其他回答
当派生类对象被分配给基类对象时,派生类对象的其他属性将从基类对象中切下(丢弃)。
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
}
我刚刚遇到了切片问题,很快就到了这里。所以让我再加上两美分。
让我们来举一个“生产代码”(或类似代码)的例子:
假设我们有一个可以调度动作的东西。例如,控制中心UI。此UI需要获取当前可以调度的事物的列表。因此,我们定义了一个包含分派信息的类。让我们称之为行动。因此,Action有一些成员变量。为了简单起见,我们只有2,即std::string名称和std::function<void()>f。然后它有一个void activate(),它只执行f成员。
因此,UI得到了一个std::vector<Action>。设想一些功能,如:
void push_back(Action toAdd);
现在,我们已经从UI的角度确定了它的外观。到目前为止没有问题。但是另一个从事这个项目的人突然决定,Action对象中有一些特殊的动作需要更多的信息。无论出于什么原因。这也可以通过lambda捕获来解决。此示例并非取自代码1-1。
所以这家伙从《行动》中派生出来,以增添自己的味道。他将自己制作的课程的一个实例传递给push_back,但随后程序就失控了。
那发生了什么?正如您可能已经猜到的:对象已被切片。
实例中的额外信息已经丢失,f现在容易出现未定义的行为。
我希望这个例子能给那些在谈论以某种方式派生的A和B时无法真正想象事情的人带来启发。
谷歌第三次匹配“C++切片”给了我这篇维基百科文章http://en.wikipedia.org/wiki/Object_slicing这(很热,但前几篇文章定义了问题):http://bytes.com/forum/thread163565.html
因此,当您将子类的对象分配给超级类时。超类对子类中的附加信息一无所知,并且没有空间存储它,因此附加信息被“分割”。
如果这些链接没有提供足够的信息来获得“好答案”,请编辑您的问题,让我们知道您还需要什么。
“切片”是指将派生类的对象分配给基类的实例,从而丢失部分信息-其中一些信息被“切片”掉。
例如
class A {
int foo;
};
class B : public A {
int bar;
};
因此,类型B的对象有两个数据成员,foo和bar。
那么如果你要写这个:
B b;
A a = b;
然后b中关于成员栏的信息在a中丢失。
好的,在阅读了许多解释对象切片的文章后,我会尝试一下,但不知道它是如何变得有问题的。
可能导致内存损坏的恶性场景如下:
类在多态基类上提供(意外地,可能是编译器生成的)赋值。客户端复制并切片派生类的实例。客户端调用一个虚拟成员函数,该函数访问切片状态。