How to hide "delete" on a class hierarchy?
So I am migrating from an "owned" object model to a "managed" object model in a project I am doing. Currently to make a new Thing one does
Thing *thing = new Thing();
and to get rid of it and destroy it the owner does
delete thing
Now there are a lot of "delete thing"s out there and many of them are deleting from a superclass of Thing pointer because the superclass has a virtual destructor.
Now in the managed model there is a base class with a virtual destructor which the manager will delete. The user is supposed to call "release" on it NOT delete.
So I would like to somehow at compile time reject "delete thing" as a compile time error. Making the destructor "protected" doesn't se开发者_开发技巧em to work because of the virtual destructor on the base. And it needs to be at least protected for subclasses (I think).
Anyone have any ideas?
You need to make the destructors protected on both your base and your subclasses. It should work okay then.
For example the code below generates compile time errors for both delete
lines.
class A
{
protected:
virtual ~A() {}
};
class B : public A
{
protected:
virtual ~B() {}
};
int main()
{
B* b = new B;
A* a = new B;
delete b;
delete a;
return 0;
}
Sure; override operator delete
in your class, and make it private:
struct Foo
{
private:
void operator delete(void*); // no body (never called)
};
You have a number of conflicting goals here. Are you trying to restrict use of delete
on a single type, or on an entire class hieararchy? I think you need to look into using custom allocation/deallocation functions (also known as opeartor new
and operator delete
). In particular, you will want your object to have its own operator new
and operator delete
functions (possibly with extra parameters) to make sure the object gets allocated and deallocated correctly.
I won't explain the use of those functions here, as writing a correct (e.g. exception-safe, etc.) allocation/deallocation function is not the simplest of tasks, and there are a number of additional difficulties to be wary of. As a result, you're best off finding a good piece of documentation on writing them (and I don't know of one offhand, sorry).
Ok - yes if I override operator delete on a base class if will cause delete to fail, however it needs to be functional as it IS called when the virtual destructor is done.
In my case I also have to make sure the base "object" interface for the equivalent of IUnknown in com has a protected destructor and constructor because the smart pointers do an implicit cast to one of these and this would be flawlessly passed to delete and compile !!! (and crash the app too)
so I have
class ObjectInterface
protected:
~ObjectInterface();
public:
virtual int method1() = 0;
...
};
class ObjectBase
: public ObjectInterface
, public ObjectImpl // has virtual destructor on it
{
protected:
static void operator delete(void *p) { ::operator delete(p); }
public:
int method1(); // default impl
};
class MyObject
: public ObjectBase
{
protected:
MyObject();
~MyObject();
public:
static SharedPointer<MyObject> create()
{
return(SharedPointer<MyObject>(new MyObject());
}
};
SharedPointer<MyObject> sp = MyObject::create();
MyObject *mo = sp;
sp = NULL; // fine does actual delete inside ObjectImpl
delete sp; // compile error
delete mo; // compile error
精彩评论