20

我有一个宠物项目,我用它来试验 C++11 的新特性。虽然我有 C 方面的经验,但我对 C++ 还是很陌生。为了训练自己掌握最佳实践(除了大量阅读),我启用了一些严格的编译器参数(使用 GCC 4.4.1):

-std=c++0x -Werror -Wall -Winline -Weffc++ -pedantic-errors

这对我来说效果很好。到现在为止,我已经能够解决所有的障碍。但是,我需要enable_shared_from_this,这给我带来了问题。编译我的代码(可能由 触发)时,我收到以下警告(在我的情况下是错误-Weffc++):

base class ‘class std::enable_shared_from_this<Package>’ has a non-virtual destructor

所以基本上,我对这个实现有点困扰enable_shared_from_this,因为:

  • 用于子类化的类的析构函数应该始终是虚拟的,恕我直言。
  • 析构函数是空的,为什么还要它呢?
  • 我无法想象有人会想通过引用来删除他们的实例enable_shared_from_this

但我正在寻找解决这个问题的方法,所以我的问题是,有没有合适的方法来处理这个问题?并且:我认为这个析构函数是虚假的,还是有真正的目的,我是否正确?

4

3 回答 3

27

用于子类化的类的析构函数应该始终是虚拟的,恕我直言。

仅当要通过指向基类的指针删除派生类的实例时,才需要基类中的虚拟析构函数。

在类中拥有任何虚函数,包括析构函数,都需要开销。Boost(以及 TR1 和 C++11 标准库)不想仅仅因为您需要能够shared_ptrthis指针中获取 a 就强迫您拥有这种开销。

析构函数是空的,为什么还要它呢?

如果您没有用户定义的构造函数,编译器会为您提供一个,所以这并不重要。

我无法想象有人会想通过引用来删除他们的实例enable_shared_from_this

确切地。

至于编译器警告,我会忽略警告或禁止它(代码中的注释解释你这样做的原因)。有时,尤其是在“迂腐”警告级别,编译器警告没有帮助,我会说这是其中一种情况。

于 2010-04-03T16:33:38.650 回答
10

我同意詹姆斯的描述,但会补充

仅当您想以虚拟方式销毁该类的实例时,才需要虚拟析构函数。情况并非总是如此,但是如果一个基类不打算被虚拟销毁,它应该防止它

所以我会改变

用于子类化的类的析构函数应该始终是虚拟的,恕我直言。

这是:

用于子类化的类的析构函数应始终为virtualprotected

于 2010-04-03T17:00:50.063 回答
4

有没有合适的方法来处理这个?

不要-Weffc++一直使用。有时打开它以检查您的代码很有用,但并不是真正永久使用它。它会产生误报,并且这些天并没有真正维护。不时使用它,但请注意,您可能不得不忽略一些警告。理想情况下,只需记住 Meyers 书中的所有建议,然后你就不需要它了 ;-)

我认为这个析构函数是假的,或者它有真正的目的吗?

不,这不是虚假的,并且有真正的目的。 如果它没有被定义,它将被隐式声明为public,以防止它被显式声明为protected

于 2012-05-06T15:13:42.660 回答