一个简单的层次结构:

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/

10-09 13:15