2009-11-02 63 views
3

因此,我正在从一个“拥有”对象模型迁移到我正在执行的项目中的“受管理”对象模型。目前做一个新的东西一个不如何隐藏类层次结构中的“删除”?

Thing *thing = new Thing(); 

,并摆脱它,破坏它的主人并

delete thing 

现在有很多的“删除事” S那里,很多的他们正从 Thing指针的超类中删除,因为超类具有虚拟析构函数。

现在在托管模型中有一个带有虚拟析构函数的基类,管理员将删除该基类。用户应该调用“释放”而不是删除。

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

任何人有任何想法?

回答

2

当然;在你的类中重写operator delete,并使其私人:

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

此,如果它通过一个虚拟的析构函数称为将无法正常工作。 – coppro 2009-11-02 21:59:03

+1

使析构函数为私有且虚拟的,提供空的析构函数体。让经理类成为层次结构基础的朋友。这样,子类可以通过基指针在头上进行管理,但只能由管理者进行管理。 – 2009-11-02 22:02:03

+0

如果你在你的基类中这样做,它会工作。但是,它也会限制'new'的使用(因为'new'需要调用'operator delete'是'operator new'成功,但是构造函数被抛出),所以你需要使用'friend'和可能的工厂方法来解决这个问题。 – 2009-11-02 22:06:44

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

是的,然后你可以和你的经理保持联系,这样可以破坏你的对象。 – 2009-11-02 22:13:00

+0

哪个编译器? 我刚刚在Visual C++ 里面编译了这个代码,没有任何错误 – 2009-11-02 22:16:04

+0

赦免 - 我的错误两个文件同名:) 它会产生错误。现在试图在现有类上实现平衡,并仍允许通过模板访问超类基本方法。 – 2009-11-02 22:42:29

0

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

我不会在这里解释这些函数的用法,因为编写正确的(例如异常安全的等)分配/释放函数不是最简单的任务,并且还有一些额外的困难警惕。因此,你最好找到一份关于写作的好文件(我不知道一个是否定的,对不起)。

+0

是的,但是:)我想强制用户使用“创建”和“释放”而不是overidden new/delete'cause“删除*之后的*析构函数(和new之前)带有对象池不希望析构函数调用。当refcount变为0时(你不想允许在refcounted对象上删除)也许是特殊的或删除但是受控的。目的是想方设法捕获对象上所有使用“delete”的地方,并使其成为编译时错误,除了管理器内部将从基类超类中删除。 – 2009-11-02 22:28:24

+0

您可以尝试将基类的delete操作符声明为私有的,以便它不能从外部使用,除了该对象可以用全局删除(“:: delete ptr”)故意解除分配。然后你可以让你的经理成为一个朋友(或者只是让它使用全局删除并且让操作员不确定)。 – coppro 2009-11-02 23:20:44

0

好吧 - 是的,如果我重写操作符删除基类,如果会导致删除失败,但它需要功能,因为它是在虚拟析构函数完成时调用。

在我的情况下,我还必须确保在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