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

发布于 2024-12-21 15:17:10 字数 314 浏览 3 评论 0原文

我注意到我的代码中由于某种原因没有发生虚拟覆盖。我广泛使用多态性,以便可以使用类似 categories.baseFunc() 的构造,其中 baseFunc 调用在 Derived 中重写的虚拟函数。

在什么情况下不会发生 vtable 构造并且多态行为变得不可靠?

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

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

I've noticed that virtual override is not occurring for some reason in my code. I'm extensively using polymorphism so that I can use constructs like derived.baseFunc(), where baseFunc calls a virtual function overriden in Derived.

In which cases does vtable construction not occur and polymorphic behavior becomes unreliable?

Note: for a simple case, everything works fine, so code doesn't need to be posted.

Update: The vtables look all right. It seems that there's a clusterf**k of namespacing that may be the issue. Plus, copy-pasting the code to new file and removing the namespaces fixes the issue.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

¢蛋碎的人ぎ生 2024-12-28 15:17:10

由于没有代码,所以很难确定什么,但这里有一些疯狂的猜测/选项

  • 您实际上并没有重写该方法。你可能认为你有,但事实上你可能错了。例如:

    结构基{
       虚拟 int f(int); 
       虚拟 int g() const;
       虚拟~Base();
    };
    结构派生:基{     
       int f(); //不覆盖Base::f
       int g(); //不覆盖Base::g
    };
    
  • 从构造函数调用虚函数不会按您的预期工作。例如,

    结构基础
    {
        根据()
        {
            f();
        }
        虚拟无效 f() {}
        虚拟~Base();
    };
    结构派生:基类
    {
        无效 f() { cout << “衍生的”; }
    };
    
    导出d; //派生不会被打印
    
  • 某些构造不调用虚拟调度,例如限定的函数调用:ClassName::MethodName()

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

Since there is no code, it's hard to say something for certain, but here are some wild guesses/options

  • You didn't actually override the method. You may think that you have, but in fact you may be mistaken. For example:

    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
    };
    
  • Calling of a virtual function from the constructor doesn't work as you'd expect. For example,

    struct Base
    {
        Base()
        {
            f();
        }
        virtual void f() {}
        virtual ~Base();
    };
    struct Derived : Base
    {
        void f() { cout << "Derived"; }
    };
    
    Derived d; //Derived will NOT be printed
    
  • Some constructs don't invoke virtual dispatch, such as qualified funcion calls: ClassName::MethodName()

In any case, for any polymorphic class the vtable is always there, so don't blame the compiler :)

策马西风 2024-12-28 15:17:10

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

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

  1. 既然您说过对于衍生.baseFunc()类型的情况不会发生覆盖,请检查衍生是对象还是引用。请记住,运行时多态性仅适用于指针和指针。引用。

  2. 函数签名对于成功覆盖很重要:

    结构基础
    {
       虚拟无效 foo (int) {}
    };
    
    结构派生:基类
    {
       virtual void foo () {} // 糟糕,这个 `foo` 与 `Base::foo` 不同
    };
    

Any conforming compiler will have proper vtable and polymorphism in place. In properly written code, overriding always happens.

You need to check for some common coding mistakes in your code. For example:

  1. Since you said that overriding is not happening for derived.baseFunc() kind of cases, check whether derived is an object or reference. Remember that runtime polymorphism is applicable only via pointers & references.

  2. Function signature is important for successful overriding:

    struct Base
    {
       virtual void foo (int) {}
    };
    
    struct Derived : Base
    {
       virtual void foo () {} // oops, this `foo` is different than `Base::foo`
    };
    
甜`诱少女 2024-12-28 15:17:10

如果您的代码正确,则虚拟函数将按预期工作。作为一种优化,如果 100% 确定关于静态类型动态类型在此调用范围内具有“静态”性质,则编译器可以将虚拟函数调用转换为普通函数调用,即,在编译时可以确定调用发生在无法更改的编译时已知类型上,因此该函数不可能是除一个具体函数之外的任何其他内容。
大多数时候,情况就是这样,因为您通过强制转换或作用域解析显式告诉编译器。无论如何,它仍然会按预期工作,没有明显的差异(不同的机器代码,肯定更高效,但行为相同)。

这与 vtable 的生成无关。无论如何都会生成 vtable(如果编译器使用 vtable 来实现虚拟继承,大多数/全部都会这样做,但严格来说没有)。

如果它没有按预期工作,您可能隐藏 虚函数(无意中)。

If your code is correct, then virtual functions will work as expected. The compiler may, as an optimization, transform virtual function calls into normal function calls if it is 100% certain about the static type that the dynamic type is of "static" nature for the scope of this call, i.e. it is certain at compile time that the call happens on a compiletime-known type that cannot change, and thus the function cannot possibly be anything else than exactly one concrete function.
Most of the time, this is the case because you explicitly tell the compiler either with a cast or scope resolution. Regardless, it will still work as expected with no observable difference (different machine code and more efficient for sure, but same behaviour).

This is irrespective of generation of a vtable. The vtable is generated anyway (if the compiler uses vtables to implement virtual inheritance, which most/all do, but strictly do not have to).

If it does not work as expected, you probably hide the virtual function (unintentionally).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文