How does the derived class destructor get invoked being private in the following program?
Asked Answered
S

2

10
#include<iostream>

class base
{
   public:
       virtual ~base(){std::cout << "base\n";}
};
class derived : public base
{
   private:
        ~derived(){std::cout << "derived\n";} /* destructor is private */
};
int main()
{
      base *pt= new derived;
      delete pt;
}

The above program compiles and runs fine. How does the derived class destructor get invoked being private ?

Supererogation answered 18/11, 2013 at 4:14 Comment(6)
Would you expect a compile-time error, or a run-time error?Copter
I would not get any error. I am interested in knowing how, in the above program, the destructor is getting invoked ! (it should not get invoked as it has been declared under private specifier.)Supererogation
If it should not be invoked, but you try to invoke it anyway, then there should be an error signalled at some point. I'm asking you at which point you think it's reasonable and appropriate to signal such an error.Copter
I got your point. The compiler is not able to signal the error as I am trying to delete a base class pointer which has a public detructor.Supererogation
Exactly. Not only that, but it would be wrong to do so, because base promises the availability of the destructor and derived should not break what base promises.Copter
@KaustavRay, this is useful when you want to force the caller coding base on interface instead of concrete class.Endplay
K
1

This will happen not only with destructors.

You can override any virtual public function with a private one.

#include<iostream>

class base
{
   public:
       virtual void x(){std::cout << "base\n";}
};
class derived : public base
{
   private:
        void x(){std::cout << "derived\n"; base::x();}
};
int main()
{
      base *pt= new derived;
      pt->x(); //OK
      //((derived *)pt)->x();  //error: ‘virtual void derived::x()’ is private
      derived *pt2= new derived;
      //pt2->x();  //error: ‘virtual void derived::x()’ is private
      ((base *)pt2)->x(); //OK
}

Upside/downside of this is you will have to use pointer to base to access this method. This feature is one of ways to separate public API from customized implementation.

So, in other words, your destructor is getting called because it was declared as public in base and you are calling it trough pointer to base.

Kine answered 18/11, 2013 at 16:21 Comment(3)
I am calling the pointer to base but as it has been also declared as virtual in the base class it should call the derived class destructor first prior to the base class destructor.Supererogation
exactly. Your program prints "derived\nbase\n". "private" keyword does not mean this function cant be called. it means that it cant be called trough this class public interface. If in your case you would write "derived *pt= new derived; delete pt;" you would get an error.Kine
when you do base *pt = new derived; you are doing base pt->destructor = derived->destructor; then pt->destructor is public, when you call it it calls internally derived->destructor, which is private but called from the same classClaudineclaudio
S
0

That may be surprising, but if you think about it, it's perfectly logical.

What the compiler sees is that you delete a pointer-to-base, which has an accessible destructor. So it has no reason to complain about what you're doing. Incidentially, it's a virtual destructor, but that's not something to complain about either.

At runtime, the virtual destructor is invoked. Since it turns out that the pointer-to-base is really pointing at a derived object, consequently the derived constructor needs to be invoked first.
"But that one is private!" says you. That's right, however, there is no notion of public/private during runtime. So, again, there is no reason for anything bad to happen. No error is generated.

Scribe answered 18/11, 2013 at 16:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.