VTBL是否包含指向非虚函数的指针?

时间:2017-07-13 13:00:24

标签: c++

我很难理解为什么下面的代码会打印C :: f2而不是B :: f2。

From Charles Bailey answer:

  

当调用非虚函数时,实现必须使用   调用函数的对象的静态类型   确定要调用的正确函数。存储在vtable中的函数   由vptr访问将取决于动态类型   对象,而不是任何静态类型的引用或指针   正在访问。

我有点失落,在A :: f1里面有一个对f2的调用。编译器如何知道调用哪个方法?

我的说法:

  1. 编译器以某种方式重述我们是C类型的对象。
  2. 编译器检查C是否包含非虚方法名称f2。 一个。如果是的话,运行它。 湾使用对象的指针访问他的vtbl并运行正确的f2。
  3. 我是对的吗?

    struct A
    {
        void f1()
        {
            f2();
        }
        virtual void f2()
        {
            cout<<"A::f2"<<endl;
        }
    };
    struct B:public A
    {
        virtual void f2()
        {
            cout<<"B::f2"<<endl;
        }
    };
    struct C:public B
    {
        void f2()
        {
            cout<<"C::f2"<<endl;
        }
    };
    int main()
    {
        C c1;
        c1.f1();
        return 0;
    }
    

1 个答案:

答案 0 :(得分:4)

每个成员函数都有一个隐式this参数。 thisf1的静态类型始终为A * const。对于任何成员函数都是如此。隐式对象参数的静态类型是封闭类,其中函数已定义

f1内的来电被解析为this->f2()。由于这是通过指针调用,因此动态调度函数f2。尽管f1不是虚拟的,但总是会被静态调度调用。

通过编译器使用的任何机制(VTable是实现细节,而不是C ++标准本身强制要求),我们可以调用C::f2

所以你的假设需要一些修改,我会说。

按照您在评论中指定的方式回答您的问题。 C::f2是虚拟的。您可能在覆盖它时省略了虚拟说明符,但没有&#34; unvirtualising&#34;它