开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜