Tip 12: Why Inheriting from a Class That Has No Virtual Destructor is Dangerous
Classes with a non-virtual destructor aren't meant to serve as base classes (such classes are usually known as "concrete classes"). std::string, std::complex, and std::vector are concrete classes. Why is inheriting from such classes not recommended? When you use public inheritance, you create an is-a relationship between the base class and its derived classes. Consequently, pointers and references to base can actually point to a derived object. Because the destructor isn't virtual, C++ will not call the entire destructor chain when you delete such an object. For example:
class A
{
public:
~A() // non virtual
{
// ...
}
};
class B: public A /* bad; A has a non virtual dtor*/
{
public:
~B()
{
// ...
}
};
int main()
{
A * p = new B; /*seemingly OK*/
delete p; /*trouble, B's dtor not called*/
}
The result of failing to invoke an object's destructor is undefined. Therefore, you shouldn't use publicly inherit from such classes. In particular, don't derive from STL containers and std::string, as tempting as it may seem.
Tip 13: Declaring Nested Classes as Friends of Their Enclosing Class
When you declare a nested class as a friend of its containing class, place the friend declaration after the declaration of the nested class, not before it:
class A
{
private:
int i;
public:
class B /*nested class declared first*/
{
public:
B(A & a) { a.i=0;}; /*access A's private member*/
};
friend class B;/*friend declaration at the right place*/
};
If you place the friend declaration before the nested class's declaration, the compiler will discard the declaration since the friend class hasn't been seen yet.