编译器真的强制执行纯虚拟析构函数吗?

Does compiler really enforce implementation of pure virtual destructor?

为了验证语句“编译器和链接器强制存在纯虚拟析构函数的函数体。geeksforgeeks article,我编译了这段代码:

class Base
{
public:
    virtual ~Base()=0; // Pure virtual destructor
};

class Derived : public Base
{
public:
    ~Derived()
    {
        std::cout << "~Derived() is executed";
    }
};

int main()
{
    //Derived d;   <<<
    return 0;
}

编译无误。那么为什么在这种情况下编译器没有选择强制函数体的存在呢?

因为如果您执行 ODR1 违规,编译器(实际上是整个翻译过程)没有强制执行任何操作.根据 [basic.def.odr/4]:

处的 C++ 标准

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see [class.ctor], [class.dtor] and [class.copy]). An inline function shall be defined in every translation unit in which it is odr-used.

编译器完全有权判断您的程序实际上并未使用2 Derived 的析构函数(因此 [=11 的析构函数) =]), 只是懒得通知你。


1 One D定义 Rule
2 What does it mean to “ODR-use” something?

Does compiler really enforce the implementation of the pure virtual destructor?

不,编译器不会这样做。

编译器将编译单元编译成object个文件,这就是为什么

compiled without any error.

我认为几乎每个编译器都能毫无错误地编译它。但是 linker 会抱怨。编译器只是将代码添加到 object 文件,以及由 linker 绑定的传入和传出引用(对于静态 linking)。

当然,如果您再次 comment-in 行 Derived d;,程序将不会 link,请参阅 online demo

更新

你在问题中显示的只是一个编译单元,如果你link它是一个程序,linker 可能会删除未使用的代码。 StorryTeller's answer 说了很多。

如果你 comment-in 在 main 中使用 Derived 并将 Base class 的定义复制到另一个编译单元并在那里添加析构函数实现,你会看到两者将被 link 编辑在一起,并且生成的程序将 运行 没有任何错误。编译器本身并不关心您是否包含 headers 中的定义。我不建议为了高效编程而这样做,而是为了理解为什么编译器传统上不关心定义的完整性。大多数 real-world 编译单元通常是不完整的。