Sur*_*ayi 1 c++ vtable vptr object-slicing
在对象切片中,当派生类对象复制到基类对象时,派生类的_vptr是否也会像基类的其他成员一样复制到基类的_vptr?如果没有,为什么?
class Base {
public :
virtual void Display() { cout << "In Base" << endl; }
};
class Derived:public Base {
public:
void Display() { cout << "In Derived" << endl; }
};
int main()
{
Derived objD;
Base objB;
objB = objD;
objB.Display();
}
Run Code Online (Sandbox Code Playgroud)
我观察到上述代码片段的以下结果。
Output
In Base
Run Code Online (Sandbox Code Playgroud)
vptr 未被复制。让我们尝试推理一下原因。
查看您的主要功能:
Derived objD;
Base objB;
objB = objD; // <-- HERE
objB.Display();
Run Code Online (Sandbox Code Playgroud)
在第 3 行中,您将 objD 分配给 objB。这实际上是调用Base的赋值运算符(自动定义的):
Base& operator=(const Base& other)
Run Code Online (Sandbox Code Playgroud)
并将 objD 作为 Base& 传递。所以,你的问题变成了“赋值运算符是否复制 vptr”?答案是不”。默认赋值运算符仅复制类上的字段。
你可能会问,“为什么它不复制 vptr 呢?” 原因是,如果复制 vptr,基类上的方法最终将使用派生类上实现的方法。但是,总的来说,这些方法可以使用仅存在于派生类中(并且不存在于基类中)的数据成员。因此,调用这些方法是无意义的(数据在逻辑上不存在于基类中),因此语言正确地选择不这样做。
主要问题是,当您将 Derived 类分配给 Base 类时,您分配给的变量仅保存 Base 类的字段,因此 Derived 类中不在 Base 类中的字段不会保存在 Base 类中。复制的。因此,在基类上调用时,派生类中的方法没有意义。
请注意,如果您要将 Base 指针或 Base 引用分配给 Derived 类,则情况并非如此。在这种情况下,原始的派生类实例仍然存在。它位于内存中的某个位置,并且具有所有 Base+Derived 类字段。因此,在该实例上调用的派生类的方法将有权访问这些字段,因此能够调用这些方法仍然有意义。
这就是为什么在 C++ 中,要实现多态性(通过虚拟方法),您需要使用引用或指针。请参阅此处的类似讨论: 为什么多态性在没有指针/引用的情况下不起作用?