【发布时间】:2016-04-02 08:08:59
【问题描述】:
我想声明一个带有虚拟析构函数的纯抽象基类。我知道三种方法可以做到这一点,但我不知道哪种方法最好,或者为什么。
我的目标是以最佳实践 C++11 风格实现抽象基类接口,并具有最佳运行时性能。特别是,我想提供无操作析构函数的内联/消除。我还想消除与重复 vtable 相关的警告,方法是选择不生成重复 vtable 的实现,或者做出明智的决定来抑制警告。
以下是我所知道的实现抽象基类的三种方式:
选项#1
/// A.h:
class A {
public:
virtual ~A() {}
virtual int f() = 0;
};
选项 #2
/// A.h:
class A {
public:
virtual ~A();
virtual int f() = 0;
};
/// A.cpp:
A::~A() {}
选项#3
/// A.h:
class A {
public:
virtual ~A() = default;
virtual int f() = 0;
};
这些是我唯一的选择吗?
#1、#2、#3 中的哪一个被认为是最佳实践?如果有权衡(例如运行时与编译时性能),请描述它们。
使用选项#1,内联析构函数是否会被内联?
我了解选项 #1 会将 vtable 放入每个翻译单元。选项 #1 在 clang 中生成 -Wweak-vtables 警告,并包含在 gcc[1] 中的“模糊链接”类别中。选项 #3 不会生成 clang 警告——这是否意味着选项 #3 不会生成 vtable?
选项 #3 与其他选项有何不同?
其他问题已经讨论了关于 clang 警告的类似问题,但我无法找到具体解决哪个选项被认为是最佳实践以及为什么的问题。
【问题讨论】:
-
CppCoreGuidelines 有一个关于此类问题的好部分,可能值得您阅读。
-
我做科学计算,在我的领域,这些变体都没有用于多态性。对于真正对性能至关重要的任务,请查看 static polymorphism 或 Barton-Nackman-Trick
-
@Maikel 是的,我也使用这些技术。但是这个问题是关于普通的基于 vtable 的多态性技术。
-
那对不起,我只是希望能帮上忙。好吧,核心指南建议使用变体 C,但我认为您所要求的详细程度并未对其进行解释。 :-(
-
您实际上/技术上还有第四个选项,尽管它对您没有多大帮助。在 A.cpp 中的选项#2 中,您可以使用
A::~A() = default;而不是A::~A() {}。