为什么gcc和clang允许我构造一个抽象类?

Mat*_*att 24 c++ gcc abstract-class clang pure-virtual

以下代码编译了广泛的gcc和clang版本 - 在编译并使用gcc 5.3.1运行时,它会打印出来

一个()

然后以纯虚拟调用错误中止.

#include <stdio.h>

class A
{
public:
    A() {
        printf("A()\n");
    }
    virtual void b() const = 0;
};

int main()
{
    const A& a{};
    a.b();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我意识到绑定对临时的引用并不理想(虽然我认为这种情况被某种生命周期扩展所覆盖) - 但它也适用于尝试调用一个带有const引用的方法,如:

Foo({});
Run Code Online (Sandbox Code Playgroud)

为方便起见,这里是一个用clang 3.2 编译的例子:Compiler Explorer

Nic*_*las 16

为什么gcc和clang允许我构造一个抽象类?

因为根据标准他们被打破了.

10.4节定义了抽象类的工作原理.它包含这一行(在C++ 14中):

除了作为派生自它的类的子对象之外,不能创建抽象类的任何对象.

使用braced-init-lists的引用的初始化规则将构造一个临时的并将其绑定到引用.临时工是物.因此,您在上面编写的代码将尝试创建"抽象类的对象",而不是"从其派生的类的子对象".

标准明确禁止的东西.在这方面,标准没有含糊之处.虽然10.4,p3确实指定了编译器需要的位置,如果你键入它们(将抽象类声明为函数参数,显式转换等),那么标准仍然要求实现禁止构造抽象类作为某些东西除了"从它派生的一个类的子对象".

临时不是"从中派生出来的类的子对象".因此,编制者有义务禁止这样做.

任何没有bug的编译器.

  • @Matt:那你应该把bug报告给`gcc`和`clang`.恭喜!!! (2认同)