简体   繁体   中英

C++ virtual destructor & vtable

I have some specific questions on virtual destructors and vtable.

Suppose I have the following code:

class Base
{
public:

    virtual ~Base();

};

class Child : public Base
{
public:

    ~Child();
};

Questions:

  1. Where is the vtable stored? Is it always in the base class and all sub-classes simply keeps a pointer to it?
  2. Adding a virtual method only increases the sizeof(class) by 8 bytes right? (assume 64bit system) How about base class if it stores the table?
  3. Creating an instance of type Child via the new operator then delete ... will the Base destructor be called? (I'm asking because Child class's destructor isn't virtual ... does that mean it only affects sub-class of Child?).

The explanation below assumes that virtual dispatch implementation used by the compiler is based on virtual tables.

  1. Each class with virtual methods (declared or inherited) has its own virtual table. If a subclass overrides a virtual member function in the base, a pointer to the overriding function is placed in the class's vtable; otherwise, a pointer to base class implementation is kept in place.

  2. Adding the first virtual function increases the size of the class instance by the size of vtable pointer. Virtual functions after the first one do not add to the size of the instance.

  3. Since ~Base is virtual, the ~Child is virtual as well, even though virtual keyword is omitted. In case of an override, virtual keyword is optional.

Creating an instance of type Child via the new operator then delete ... will the Base destructor be called?

Not in the original question code, because you don't have Child inheriting from Base .

Assuming that's a mistake, and we fix it, then ~Base would be called when you destroy a Child even if it weren't virtual, just because the base-class sub-object is destroyed as part of the normal destruction sequence.

The reason for virtual destructors is so you can delete a Child via a Base * and still have ~Child invoked correctly.

Eg, with:

struct Base { ~Base(); };
struct Child: Base { ~Child(); };

struct VBase { virtual ~VBase(); };
struct VChild: VBase { ~VChild(); };

this works for both hierarchies:

template <typename Derived>
void test_static() {
  Derived d;
}
test_static<Child>();  // ~Child then ~Base invoked when d is destroyed
test_static<VChild>(); // ~VChild then ~VBase invoked when d is destroyed

but this only works with a virtual destructor:

template <typename Derived, typename Base>
void test_dynamic() {
  std::unique_ptr<Base> p(new Derived);
}
test_dynamic<Child, Base>;  // only ~Base invoked when p destroyed
test_dynamic<VChild,VBase>; // ~VChild then ~VBase invoked as before.

As for the vtable questions, it's an implementation detail whether one exists, and if so where it is, and you don't need to worry about it.

Every class with virtual methods (declared/inherited) has its own virtual table(vtable). When a virtual method (any, not just the destructor) is declared virtual, all overrides of that method in derived classes are automatically virtual. The compiler also adds _vptr at the beginning of any such classes having virtual methods. This _vptr will be filled when the class's object is created and will point to the vtable of that class. A virtual destructor is treated the same way as any other virtual function. In your example since ~Base is virtual, ~Child will be virtual as well.

Suppose if you do:

Child *child = new (class Child);
delete(child);

Here, child->_vptr would be pointing to Child's vtable. So during delete, ~Child will be called first & followed by ~Base (in the reverse order of construction).

Alternately if you do,

Base *base = new (class Child);
delete(base);

Here, base->_vptr would be pointing to Child's vtable. So during delete, ~Child will be called first & followed by ~Base from the vtable.

In gdb, we can verify this _vptr by running this command,

"info vtbl base" or "print *base"

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