5

我想确保没有人能够从我的类层次结构中删除任何对象,而不是使用提供的 Destroy 方法。

基本原理是该层次结构中的任何对象都需要在开始销毁自身之前采用特殊的写入互斥锁,以确保在另一个线程正在使用它们时不会删除对象。

我知道我可以通过引用计数来防止这个问题,但是就潜在的性能影响和内存分配而言,这对系统来说也是一个更大的变化。

有没有办法以某种方式有效/智能地保护所有析构函数,以便子类可以调用其父母析构函数,而外人必须使用 Destroy?

我想出的一种安全(即它不会腐烂)的解决方案是将所有析构函数设为私有并将每个派生类声明为基类的朋友,但我更喜欢更优雅、更少手动和更容易的东西维护(例如不需要修改基类以便从它们派生)。

有这样的东西吗?也许一些聪明的技巧可以让事情像我想要的那样“工作”?

附言。我现在选择的解决方案是不阻止任何人在所有情况下调用 delete(只是在基类中使其受到保护),而是检测这种情况并在基类析构函数中调用 abort。

4

4 回答 4

1

不要试图重新发明语言提供的生命周期机制。

要正确初始化您的类的对象,它还需要能够自行清理。

在其构造函数中传递互斥体或获取互斥体的方法,它可以在其析构函数中使用。

于 2013-03-06T11:05:56.180 回答
1

Thanks for all your feedback and discussion. Yes - it proved it's impossible to do what would be my natural first choice :( (to have the "protection" of the destructor take effect in derived classes just as it's "virtuality" does).

My solution in this particular case (solving all potential problems with being able to make hones mistakes by introducing new derived classes that violate previous agreements AND keeping the solution in one place/maintainable (no code duplication in derived classes etc)) is:

  1. Make all the existing class hierarchy destructors I can find protected
  2. Provide a Destroy method in the base class that can be used to initiate the destruction of these objects - if called the method lights up a flag on the destructed object that it was properly destroyed and then calls delete on it
  3. In the base class destructor (once we get to it) check the flag - if it's not set it means someone introduced a new class and called delete on it directly or avoided the compilers protection checks in some other way (abused some friendships etc) - I abort the application in this case to make sure the issue cannot be ignored/missed
于 2013-03-20T09:40:29.840 回答
1

我有同样的需求,但出于不同的原因。在我们公司的框架中,几乎所有的类都派生自一个公共BaseObject类。该对象使用引用计数来确定其生命周期。BaseObject特别是这三种方法:和retain(),深受Objective-C语言的启发。仅当保留计数达到0时,才在内部调用运算符。没有人应该直接调用,并且在堆栈上有实例也是不可取的。release()autorelease()deleterelease()deleteBaseObject

因此,我们所有的析构函数都应该是protectedor private。为了强制执行这一点,据我所知,从语言中这是不可能的,我编写了一个 Perl 脚本,它在源目录中查找所有析构函数并生成报告。然后相对容易检查规则是否得到遵守。

我将脚本公开,可在此处获取:https ://gist.github.com/prapin/308a7f333d6836780fd5

于 2014-07-01T20:44:30.360 回答
0

它可以在测试的帮助下完成。对于具有受保护析构函数的类,您需要 2 个测试用例:

  1. 一个函数(在一个文件中)无法编译,只需创建这样一个对象
  2. 一个函数(在第二个文件中)创建一个带有可编译的派生类的对象。

如果两个测试用例都有效,我认为你可以确保你的类得到了你喜欢的保护。

我不知道你是否能够用你的构建系统来实现它,但我有一个在git hub使用 bjam (来自 boost)的例子。代码很简单,适用于 gcc 和 msvc。如果你不知道 bjam,你应该看看 inte Jamroot.jam。我认为这个简单示例的工作原理很清楚,无需进一步评论。

于 2013-03-06T14:17:59.927 回答