How to enforce users to create objects of class derived from mine with "new" only?
To implement reference counting we use an IUnknown
-like interface and a smart pointer template class. The interface has implementation for all the reference-count methods, including Release()
:
void IUnknownLike::Release()
{
if( --refCount == 0 ) {
开发者_如何转开发 delete this;
}
}
The smart pointer template class has a copy constructor and an assignment operator both accepting raw pointers. So users can do the following:
class Class : public IUnknownLike {
};
void someFunction( CSmartPointer<Class> object ); //whatever function
Class object;
someFunction( &object );
and the program runs into undefined behavior - the object is created with reference count zero, the smart pointer is constructed and bumps it to one, then the function returns, smart pointer is destroyed, calls Release()
which leads to delete
of a stack-allocated variable.
Users can as well do the following:
struct COuter {
//whatever else;
Class inner;// IUnknownLike descendant
};
COuter object;
somefunction( &object.Inner );
and again an object not created with new
is delete
d. Undefined behavior at its best.
Is there any way to change the IUnknownLike
interface so that the user is forced to use new
for creating all objects derived from IUnknownLike
- both directly derived and indirectly derived (with classes in between the most derived and the base)?
Make the constructor private and write a static member function that uses new
class IUnknownLike{
public:
static IUnknownLike * createIUnknownLike(); { return new IUnknownLike(); }
private:
IUnknownLike (); // private ctor
};
IUnknownLike* obj = createIUnknownLike();
You can make the Base class's destructor protected and smart pointer class his friend.
Thus the users will be unable to create the instance of the class on stack. They'll have to use operator new
and smart_pointer class, that will call release and delete.
If you're really intent on doing this for so many classes, use a macro to create the factory method. Something like:
#define FACTORY(NAME) protected: NAME();\
public: static NAME* create ## NAME(){ return new NAME(); }
If you want to pass parameters to the constructors, you'll have to get fancier.
The alternative is to implement the rest of COM and have each class register a factory function with a central object creation system. While an interesting exercise, this all sounds like a terrible idea.
精彩评论