编译器真的强制执行纯虚拟析构函数吗?
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 编译单元通常是不完整的。
为了验证语句“编译器和链接器强制存在纯虚拟析构函数的函数体。”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 编译单元通常是不完整的。