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

时间:2016-05-04 01:46:38

标签: c++ gcc clang abstract-class pure-virtual

以下代码编译了各种gcc和clang版本 - 在编译并使用gcc 5.3.1运行时,它会打印

  

A()

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

#include <stdio.h>

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

int main()
{
    const A& a{};
    a.b();
    return 0;
}

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

Foo({});

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

1 个答案:

答案 0 :(得分:16)

  

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

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

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

  

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

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

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

临时不是“从中派生的类的子对象”。因此,编制者有义务禁止这一点。

任何没有错误的编译器。