I l@ve RuBoard Previous Section Next Section

1.7 Destructors of Policy Classes

There is an additional important detail about creating policy classes. Most often, the host class uses public inheritance to derive from its policies. For this reason, the user can automatically convert a host class to a policy and later delete that pointer. Unless the policy class defines a virtual destructor, applying delete to a pointer to the policy class has undefined behavior,[4] as shown below.

[4] In Chapter 4, Small-Object Allocation, you can find a discussion on exactly why this happens.



typedef WidgetManager<PrototypeCreator>


   MyWidgetManager;


...


MyWidgetManager wm;


PrototypeCreator<Widget>* pCreator = &wm; // dubious, but legal


delete pCreator;  // compiles fine, but has undefined behavior


Defining a virtual destructor for a policy, however, works against its static nature and hurts performance. Many policies don't have any data members, but rather are purely behavioral by nature. The first virtual function added incurs some size overhead for the objects of that class, so the virtual destructor should be avoided.

A solution is to have the host class use protected or private inheritance when deriving from the policy class. However, this would disable enriched policies as well (Section 1.6).

The lightweight, effective solution that policies should use is to define a nonvirtual protected destructor:



template <class T>


struct OpNewCreator


{


   static T* Create()


   {


    return new T;


   }


protected:


   ~OpNewCreator() {}


};


Because the destructor is protected, only derived classes can destroy policy objects, so it's impossible for outsiders to apply delete to a pointer to a policy class. The destructor, however, is not virtual, so there is no size or speed overhead.

    I l@ve RuBoard Previous Section Next Section