简体   繁体   中英

In which cases does vtable construction not occur?

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.

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 :)

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` }; 

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, ie 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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM