The correct way to inherit a virtual class with a non-virtual parent

I wrote this test code that uses three types: struct One is a regular type without virtual members, struct Two : One has a pure virtual function and a virtual destructor, and struct Three : Two implements the Two interface.

 #include <iostream> struct One { ~One() { std::cout << "~One()\n"; } }; struct Two : One { virtual ~Two() { std::cout << "~Two()\n"; } virtual void test() = 0; }; struct Three : Two { virtual ~Three() { std::cout << "~Three()\n"; } virtual void test() { std::cout << "Three::test()\n"; } }; int main() { Two* two = new Three; two->test(); One* one = two; delete one; } 

Not surprisingly, the result was :

Three :: test ()
~ One ()

Is there a way to fix this differently than making each destructor virtual? Or should programmers be careful not to run into this situation? It seems strange to me that there are no warnings when compiling this.

+4
source share
4 answers

The only “fix” is to not delete objects with a pointer to One .

Whether this is a common problem or not depends on how your classes are used. For example, the standard library contains structures of the unary_function type without a virtual destructor, but we are unlikely to ever see that this is misused.

+2
source

delete one causes undefined behavior, because the dynamic type of the object does not match the static type, and the static type does not have a virtual destructor.

The usual way to avoid such problems is to make the destructors both public and virtual, or protected and non-virtual (in classes that are expected to be used this way).

+2
source

You have to be careful and make one destructor virtual. Some compilers warn about this.

+1
source

If you need working destructors in derived classes, you must define them as virtual. This is the only way.

+1
source

Source: https://habr.com/ru/post/1389792/


All Articles