一个简单的层次结构:
class X
{
public:
virtual void test(){ printf("x\n");}
};
class Y : public X
{
public:
virtual void test() { printf("y\n");}
};
class Z : public Y
{
public:
void test() { printf("z\n");}
};
如果创建z的实例,则无论该实例将其转换为哪个基础,我都希望该实例的vtable指向z的测试函数:
Z myZ;
myZ.test();
((Y)myZ).test();
我在这里想念什么?
最佳答案
这是因为您进行了myZ
的实际类型转换。通过这样做,编译器将创建一个类型为(Y)myZ
的临时对象Y
,并将使用该对象来调用它的test
方法。
更长的代码等效于:
Z myZ;
Y tmp = Y(myZ);
tmp.test();
您可以看到,如果您的
test
方法以任何方式修改对象,都会发生这种情况。然后((Y)myZ).test()
不应修改myZ
。如前所述,动态分配仅需要在指针或引用上进行。
实际上,您无法区分指针与没有指针之间的区别,例如,您可以在
X
中有一个蹦床方法,类似这样,尽管您使用了指针,它仍然会调用Y::test
:class X {
public:
void call_test() {
this->test();
}
}
动态调度不会发生的事实可以看作是一种优化技术。编译器知道
((Y)myZ)
将具有Y
的虚拟表,因此可以立即调用Y::test
。关于c++ - 类继承和虚函数表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33009146/