为什么 gcc 和 clang 允许我构造一个抽象类? [英] Why do gcc and clang allow me to construct an abstract class?

查看:31
本文介绍了为什么 gcc 和 clang 允许我构造一个抽象类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The following code compiles on a wide range of gcc and clang versions - when compiled and run with gcc 5.3.1, it prints

A()

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

then aborts with a pure virtual call error.

#include <stdio.h>

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

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

我意识到将引用绑定到临时对象并不理想(尽管我认为这种情况包含在某种生命周期扩展中)-但是在尝试调用需要常量引用如:

I realise binding a reference to a temporary is not ideal (though I think this case is covered by some sort of lifetime extension) - but it also works when trying to call a method that takes a const reference like:

Foo({});

为了方便,这里有一个用 clang 3.2 编译的例子:编译器资源管理器

For convenience here's an example of it compiling with clang 3.2: Compiler Explorer

推荐答案

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

Why do gcc and clang allow me to construct an abstract class?

因为按照标准,它们坏了.

Because they're broken, according to the standard.

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

Section 10.4 defines how abstract classes work. It contains this line (in C++14):

不能创建抽象类的对象,除非作为从它派生的类的子对象.

no objects of an abstract class can be created except as subobjects of a class derived from it.

带有花括号初始化器列表的引用的初始化规则将构造一个临时对象并将其绑定到引用.临时对象是对象.因此,您在上面编写的代码将尝试创建一个抽象类的对象",而不是从它派生的类的子对象".

The initialization rules for references with braced-init-lists will construct a temporary and bind it to the reference. Temporaries are objects. As such, the code you wrote above will attempt to create an "object of an abstract class" as something other than a "subobject of a class derived from it."

标准明确禁止的内容.标准在这方面没有歧义.虽然 10.4,p3 确实指定了编译器在键入它们时需要彻底错误的地方(将抽象类声明为函数参数、显式转换等),但标准仍然要求实现禁止将抽象类构造为某物除了从它派生的类的子对象".

Something the standard expressly forbids. There is no ambiguity in the standard in this regard. While 10.4, p3 does specify places that the compiler is required to out-right error if you type them (declaring abstract classes as function parameters, explicit conversions, etc), the standard still requires implementations to forbid the construction of an abstract class as something other than a "subobject of a class derived from it."

临时对象不是从它派生的类的子对象".因此,编译器有义务禁止这种情况.

A temporary is not a "subobject of a class derived from it." And therefore, compilers are obligated to forbid this.

任何没有错误的编译器.

Any compiler which does not has a bug.

这篇关于为什么 gcc 和 clang 允许我构造一个抽象类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆