通过初始化列表实例化抽象类

24

我想了解为什么编译器允许以下代码进行编译

#include <iostream>

struct A
{
    A()
    {
        std::cout << "A::A\n";
    }

    virtual void f() const = 0;
};

void g(const A& a)
{
    a.f();
}

int main()
{
    g({});
}

运行时,它甚至输出 A::A

如果我用 g(A()) 替换 g({}),显然它无法编译。它会抱怨说 A 是抽象的并且不能被实例化。但是,无论是 Clang 还是 GCC 都可以编译这个代码而不产生任何警告。运行时,两个版本都打印出 pure virtual method called 并终止。


9
MSVS 终于做了正确的事情(至少我希望它是正确的),并拒绝了这段代码。 - NathanOliver
1
哇,我真的被这个迷住了。这怎么可能呢?已确认。使用C++17运行。 - Arnav Borborah
是的,这根本没有任何意义,为什么它可以编译或者说应该是可编译的。这是标准中未定义的情况还是gcc和clang都实现了的一个bug呢? - Hayt
无法在g++上编译,出现错误“无法分配抽象类型A的对象”,不确定是什么原因导致差异。 - Benson Lin
1
{}合法的规则很奇怪。实现这些奇怪的规则似乎在gcc和clang中留下了漏洞。 - Yakk - Adam Nevraumont
显示剩余3条评论
1个回答

14

这看起来像是已知的g++漏洞编号70939

在所有版本的g++中允许创建抽象类对象

g++可以成功编译格式不正确的C++程序

class A {
public:
    A() {
        printf("A()\n");
    }
    virtual void b() const = 0;
};
int main() {
    const A& a{};
    a.b();
    return 0;
}

你的代码和这一行代码做了相同的事情

const A& a{}
作为g({})调用的一部分。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接