Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
201 views
in Technique[技术] by (71.8m points)

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

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

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...