编译器是否确实会实施纯虚拟驱动器的实现

Does compiler really enforce implementation of pure virtual destructor?

本文关键字:驱动器 实现 虚拟 是否 编译器 施纯      更新时间:2023-10-16

要验证语句" compiler&链接器强制执行纯虚拟破坏者的功能主体。P>

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

编译而没有任何错误。那么,为什么在这种情况下,编译器没有选择执行功能主体的存在?

,因为编译器(实际上是整个翻译过程)没有如果执行ODR 1 违反。根据[basic.def.odr/4]的C 标准:

每个程序应完全包含每个非内线的一个定义 该程序中使用ODR的功能或变量;没有诊断 必需的。该定义可以在程序中明确显示,它可以 可以在标准或用户定义的库中找到(当 适当)是隐式定义的(请参阅[class.ctor],[class.dtor] 和[class.copy])。每个内联函数应在每个中定义 使用ODR的翻译单元。

编译器完美地在其范围内确定您的程序实际上并未使用 2 Derived的破坏者(因此是Base的破坏者),并且只是不用打扰您。<<<<<<<<<<<<<<<<<<<<<</p>


1 o ne d efinition r ule
2 "使用"某物意味着什么?

编译器是否真的强制执行纯虚拟破坏者的实现?

没有编译器没有这样做。

编译器将编译单元编译到对象文件,这就是为什么它

编译没有任何错误。

我认为几乎每个编译器都会在没有任何错误的情况下进行编译。但是链接者会抱怨。编译器仅将代码添加到对象文件中,以及由链接器限制的内外引用(用于静态链接)。

当然,如果您再次发表评论Derived d;,该程序将不会链接,请参见在线演示。

更新

您在问题中显示的只是一个单个汇编单元,如果您将其链接为程序,则链接器可能会删除未使用的代码。Storryteller的答案对此说了很多。

如果您在MAIN中注释Derived使用情况,并将Base类的定义复制到另一个编译单元中并在此处添加destructor实现,您会发现两者都将链接在一起,并且结果程序将运行,而无需任何错误。编译器本身不在乎您是否包括标题的定义。我不建议这样做是为了生产性编程,而是要理解为什么编译器传统上不关心定义的完整性。大多数现实世界的汇编单元通常不完整。