在哪些情况下,vtable结构不会发生?

时间:2011-12-14 11:28:03

标签: c++ vtable

我注意到在我的代码中由于某种原因没有发生虚拟覆盖。我正在广泛使用多态,因此我可以使用像derived.baseFunc()这样的构造,其中baseFunc在Derived中调用虚函数覆盖。

在哪些情况下,vtable结构不会发生,多态行为变得不可靠?

注意:对于一个简单的情况,一切正常,因此不需要发布代码。

更新:vtable看起来很好。似乎有一个命名空间的clusterf ** k可能是问题。此外,将代码复制粘贴到新文件并删除命名空间可以解决问题。

3 个答案:

答案 0 :(得分:7)

由于没有代码,很难肯定地说出来,但这里有一些疯狂的猜测/选项

  • 您实际上没有覆盖该方法。你可能认为你有,但事实上你可能会弄错。例如:

    struct Base{
       virtual int f(int); 
       virtual int g() const;
       virtual ~Base();
    };
    struct Derived: Base{     
       int f();  //doesn't override Base::f
       int g();  //doesn't override Base::g
    };
    
  • 从构造函数中调用虚函数不会像您期望的那样工作。例如,

    struct Base
    {
        Base()
        {
            f();
        }
        virtual void f() {}
        virtual ~Base();
    };
    struct Derived : Base
    {
        void f() { cout << "Derived"; }
    };
    
    Derived d; //Derived will NOT be printed
    
  • 某些构造不会调用虚拟分派,例如合格的funcion调用:ClassName::MethodName()

在任何情况下,对于任何多态类,vtable总是存在,所以不要责怪编译器:)

答案 1 :(得分:5)

任何符合标准的编译器都将具有适当的vtable和多态性。在正确编写的代码中,覆盖总会发生。

您需要检查代码中的一些常见编码错误。例如:

  1. 由于您说derived.baseFunc()种情况没有覆盖,请检查derived是对象还是引用。请记住,运行时多态性仅适用于指针&amp;参考

  2. 功能签名对于成功覆盖非常重要:

    struct Base
    {
       virtual void foo (int) {}
    };
    
    struct Derived : Base
    {
       virtual void foo () {} // oops, this `foo` is different than `Base::foo`
    };
    

答案 2 :(得分:0)

如果您的代码是正确的,那么虚函数将按预期工作。作为优化,编译器可以将虚函数调用转换为正常函数调用,如果它是关于静态类型的100%确定,则动态类型对于此调用的范围具有“静态”性质,即在编译时确定调用发生在无法更改的编译时已知类型上,因此该函数不可能只是一个具体函数。 大多数情况下,情况就是这样,因为您使用强制转换或范围解析明确告诉编译器。无论如何,它仍然按预期工作,没有可观察到的差异(不同的机器代码,确保更有效,但行为相同)。

这与vtable的产生无关。无论如何都会生成vtable(如果编译器使用vtable来实现虚拟继承,大部分/全部都可以,但严格来说 <)>。

如果它没有按预期工作,你可能hide虚拟功能(无意中)。