如何在类层次结构中隐藏“删除”?

时间:2009-11-02 21:53:34

标签: c++

所以我正在从一个“拥有”的对象模型迁移到我正在做的项目中的“托管”对象模型。目前要做一件新的事情

Thing *thing = new Thing();

并摆脱它并摧毁它所有者

delete thing

现在有很多“删除东西”,其中很多都是从一个删除 Thing指针的超类因为超类有一个虚析构函数。

现在,在托管模型中,有一个带有虚拟析构函数的基类,管理器将删除它。用户应该在其上调用“发布” NOT delete。

所以我想以某种方式在编译时拒绝“删除事物”作为编译时错误。 由于基础上的虚拟析构函数,使析构函数“受保护”似乎不起作用。它至少需要保护子类(我认为)。

有人有什么想法吗?

4 个答案:

答案 0 :(得分:6)

您需要在基础和子类上保护析构函数。它应该可以正常工作。

例如,下面的代码会为delete行生成编译时错误。

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;
}

答案 1 :(得分:2)

不确定;在您的班级中覆盖operator delete,并将其设为私有:

struct Foo
{
private:
    void operator delete(void*); // no body (never called)
};

答案 2 :(得分:0)

这里有许多相互矛盾的目标。您是否试图限制delete在单一类型或整个类hieararchy上的使用?我认为您需要考虑使用自定义分配/释放功能(也称为opeartor newoperator delete)。特别是,您希望您的对象拥有自己的operator newoperator delete函数(可能带有额外的参数),以确保正确分配和释放对象。

我不会在这里解释这些函数的使用,因为编写正确的(例如异常安全等)分配/解除分配函数并不是最简单的任务,并且还有一些额外的困难需要警惕的。结果,你最好找到一篇关于写作的好文章(而且我不知道有哪一个,对不起)。

答案 3 :(得分:0)

好的 - 是的,如果我在基类上覆盖operator delete,如果会导致delete失败,那么它需要在虚拟析构函数完成时调用它。

在我的情况下,我还必须确保com中IUnknown等效的基础“对象”接口具有受保护的析构函数和构造函数,因为智能指针对其中一个执行隐式转换,这将完美地传递给删除并编译!!! (并使应用程序崩溃)

所以我有

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