Why do gcc and clang allow me to construct an abst

2019-01-18 18:45发布

问题:

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()\n");
    }
    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({});

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

回答1:

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

Because they're broken, according to the standard.

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."

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.