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 ?

Kaustav Ray
  • 744
  • 6
  • 20
  • Would you expect a compile-time error, or a run-time error? – n. m. could be an AI Nov 18 '13 at 13:33
  • 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.) – Kaustav Ray Nov 18 '13 at 14:59
  • 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. – n. m. could be an AI Nov 18 '13 at 16:53
  • 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. – Kaustav Ray Nov 19 '13 at 02:28
  • 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. – n. m. could be an AI Nov 19 '13 at 03:46
  • @KaustavRay, this is useful when you want to force the caller coding base on interface instead of concrete class. – ZijingWu Nov 19 '13 at 09:37

2 Answers2

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.

fsw
  • 3,595
  • 3
  • 20
  • 34
  • 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. – Kaustav Ray Nov 18 '13 at 16:52
  • 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. – fsw Nov 18 '13 at 17:16
  • 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 class – javier_domenech Nov 19 '13 at 10:58
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.

Damon
  • 67,688
  • 20
  • 135
  • 185