虚拟表和对象切片

问题描述 投票:0回答:1

在对象切片中,当派生类对象被复制到Base类对象时,Derived类的_vptr是否也像Base类的其他成员一样被复制到Base类的_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();
}

我已经观察到上述代码段的以下结果。

Output
In Base
vtable object-slicing vptr
1个回答
0
投票

所有已知的实现都使用vptr,但细节变化很大。 vptr是一种实现方式,用于表示多态类(具有虚函数的类)的对象类型,有时还包含具有虚基类的类(非常依赖于实现)。

请注意,在许多涉及多个简单继承(单个非虚拟继承)的情况下,类具有多个vptr。

vptr值是构造的最派生对象的类型的函数。

用户在其生命周期内不能更改对象的类型;在施工过程中,物体的类型在建造时会发生变化;在破坏期间,它会改变。 (在构造或销毁期间使用名称或其他类型与对象不匹配的表达式引用对象是非法的。)

您可以重用现有对象的空间来构造不同类型的对象,但它不是同一个对象:

struct X {
  A a;
  B b;
  // requires: construction doesn't throw
};

void replace (X &x) {
  x.~X(); 
  B &b = *new (&x) B; // hope no exception here
  b.f(); // use as a normal B object
  x.f(); // undefined: cannot use x as a real object
  X *p = &x; // legal: x isn't used as an object, only as an address
  b.~B(); // clean up ressources if needed
  new (&x) X; // valid: &x refers to storage, as if a void*
  // x refers to a valid X object 
}

这样的对象重用不会改变任何现有对象的类型:replace(x)不仅仅对x起作用(它通过破坏一个并重建一个),它作用于x的存储位置。在调用replace(x)之后,可以使用名称x来引用新构造的X对象,该对象有效地识别了先前存在的X对象。

对象(对象保持活动状态)的操作甚至不允许在C ++中更改其类型。 vptr无法在构造的对象上进行更改。

更改声明对象的类型会破坏C ++类型系统和声明对象的不变量。编译器不知道要销毁什么类,要调用哪些虚函数,基类所在的位置等等。这将彻底改变C ++的工作方式。很难想象与更改现有对象类型相关的语义。

© www.soinside.com 2019 - 2024. All rights reserved.