protected virtual dtor #tricky

[[boost]] P 24 explains the technique of protected virtual destructor. Here’s my take —

The superclass A destructor is called by B’s destructor. See http://www.cplusplus.com/forum/general/12344/. Remember you first clean up the outermost layer of the onion, and remember the B fields exist on the outer layer, outside A’s real estate.

Now, if someone gets hold of an A pointer, where the pointee is B, she can’t call delete on the pointer. Compile time (not run time) error. The special dtor is a protection.

class Base{
  protected: virtual ~Base(){cout <<"base dtor" <<endl;}
};
class Derived : public Base {
  public: virtual ~Derived(){cout <<"derived dtor" <<endl;}
};
int main(){
  Base * p1 = new Derived;
  Derived * p2 = new Derived;
  delete p1; //won't compile
  delete p2; // ok
}

If I swap the 2 words public and protected then I can delete Base ptr but not Derived ptr (compiler error)!

So it seems declared type must have a public dtor. In our examples, even though object is Derived, delete is allowed only on the ptr whose declared type has a public dtor.

Now, What if i have a private dtor? Probably less common, but it’s possible to invoke this private virtual dtor —

class Base{
  public:virtual ~Base(){cout <<"base dtor" <<endl;}
};
class Derived : public Base {
  private: virtual ~Derived(){cout <<"derived dtor" <<endl;}
};
int main(){
  Base * p1 = new Derived;
  delete p1; // ok private destructor called!
}

In my experiments, qq(new) is mandatory as a stackVar or this class will trigger a compiler error, because compiler can’t destroy the object automatically.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s