我已经阅读了关于vtable的内容,并且已经理解了指向基类和派生类对象的基类指针的概念。有人可以解释当基类和派生类都是对象并且派生类对象被分配给基类对象时如何创建vtable的情况。以下示例中的案例3
#include <iostream>
#include <exception>
using namespace std;
class Base
{
public:
virtual void function1() { cout<<"Base - func1"<<endl; }
virtual void function2() { cout<<"Base - func2"<<endl; }
};
class Derived1: public Base
{
public:
virtual void function1() { cout<<"Derived1 - func1"<<endl; }
};
class Derived2: public Base
{
public:
virtual void function2() { cout<<"Derived2 - func2"<<endl; }
};
int main ()
{
// Case 1
Base* B1 = new Derived1();
B1->function1();
B1->function2();
// Case 2
cout<<endl;
Base* B2 = new Derived2();
B2->function1();
B2->function2();
// Case 3
cout<<endl;
Base B3;
Derived1 D1;
B3=D1;
B3.function1();
B3.function2();
}
输出:
Derived1 - func1
Base - func2
Base - func1
Derived2 - func2
Base - func1
Base - func2
B3=Derived;
是对象切片的一个例子...只分配了基类数据成员,并且vtable指针继续指向基类函数。
你应该避免切片 - 这可能很危险(请参阅this answer的解释)。现在你知道了这个术语,你会很容易找到关于物体切片的大量阅读....
Base B3;
D1 Derived;
B3=Derived; //There is called default assignment operator
它定义如下:
Base& operator=(const Base &objectToCopy) {...}
运算符采用类型为Base
的参数,因此类型为D1
的对象被视为Base
类型的对象。这意味着赋值运算符只能看到Derived
类中的Base
字段。但是,指向vtable
(技术上是隐藏字段)的指针仍然没有被复制,因为它总是在构造函数中创建,并且它与真实对象类型永久关联。