TheFallenPickle
TheFallenPickle

Reputation: 11

Declaring Virtual Destructor in base class changes what type a pointer points to?

I ran across the following behavior writing a simple program to learn about virtual destructors. What I wanted to do was print the name of each class and then compare to what type my pointer was pointing to. I put print statements in each destructor so I could see behavior when switching between virtual and non-virtual in the base class.

Code:

class TimeKeeper {....} //non-virtual destructor in base class
class AtomicClock : public TimeKeeper {...} 

int main(){
    std::cout << "TimeKeeper Name: " << typeid(TimeKeeper).name() << std::endl;
    std::cout << "AtomicClock Name: " << typeid(AtomicClock).name() << std::endl;

    TimeKeeper *ptk = new AtomicClock(rand());

    std::cout << "ptk is of type: " << typeid(*ptk).name() << std::endl;

    delete ptk;
}

Here is the output:

TimeKeeper Name: 10TimeKeeper
AtomicClock Name: 11AtomicClock
ptk is of type: 10TimeKeeper
I am in the Base Class Destructor

However, when I change the TimeKeeper base class destructor to be virtual, the output is this:

TimeKeeper Name: 10TimeKeeper
AtomicClock Name: 11AtomicClock
ptk is of type: 11AtomicClock
I am in the Derived Class Destructor
I am in the Base Class Destructor

I understand why the dervied class destructor is being called, but I do not understand why the ptk type changed.

My Question is: Why does the type that ptk points to change when I switch to a virtual Destructor in TimeKeeper class? Or is this me not understanding how typeid works/how to use it?

Upvotes: 1

Views: 105

Answers (1)

john
john

Reputation: 87997

It's the same as the difference between calling a virtual function or a non-virtual function. You can either use the type of the expression, or you can use the type of the object. In the case of

TimeKeeper *ptk = new AtomicClock(rand());
std::cout << "ptk is of type: " << typeid(*ptk).name() << std::endl;

the expression *pkt has type reference to TimeKeeper but the object referred to has type AtomicClock. Either type could be printed by typeid. What makes the difference is whether TimeKeeper is polymorphic or not, that is whether it has any virtual methods (including a virtual destructor). If TimeKeeper is polymorphic typeid will use the type of the object otherwise the type of the expression.

Upvotes: 1

Related Questions