c++ - GCC 上虚拟继承行为的奇怪默认空构造函数

标签 c++ gcc clang virtual-inheritance

我的代码中有以下情况,即派生类具有对基类的虚拟继承:

class Base {
    int x;
public:
    Base(int x): x{x} {}
    virtual void f() = 0;
};

class Derived : public virtual Base  {
  public:
    Derived() = default;
};

class Concrete: public Derived {
public:
    Concrete(): Base{42} {}
    void f() override {}
};
链接:https://godbolt.org/z/bn1EY6
GCC(主干)给出以下错误:error: use of deleted function 'Derived::Derived()'而 Clang (trunk) 编译它没有问题。
如果我将构造函数更改为 Derived() {},GCC 可以工作而不是 Derived() = default或者在基类上定义一个空的构造函数。
为什么是= default在这种情况下删除 GCC 中的功能?

最佳答案

标准说(最新草案):

[class.default.ctor]

A defaulted default constructor for class X is defined as deleted if:

  • X is a union that ... [[does not apply]]
  • X is a non-union class that has a variant member M with ... [[does not apply]]
  • any non-static data member with no default member initializer ([class.mem]) is of reference type, [[does not apply]]
  • any non-variant non-static data member of const-qualified type ... [[does not apply]]
  • X is a union and ... [[does not apply]]
  • X is a non-union class and all members of any anonymous union member ... [[does not apply]]
  • [applies if the base is a potentially constructed subobject] any potentially constructed subobject, except for a non-static data member with a brace-or-equal-initializer, has class type M (or array thereof) and either M has no default constructor or overload resolution ([over.match]) as applied to find M's corresponding constructor results in an ambiguity or in a function that is deleted or inaccessible from the defaulted default constructor, or
  • any potentially constructed subobject has a type with a destructor that is deleted or inaccessible from the defaulted default constructor. [[does not apply]]

只有一个规则可能适用于被删除的默认默认构造函数,这取决于基类是否是潜在构造的子对象。

[special]

For a class, its non-static data members, its non-virtual direct base classes, and, if the class is not abstract ([class.abstract]), its virtual base classes are called its potentially constructed subobjects.

Derived是抽象的(因为它没有实现所有纯虚函数),并且 Base是一个虚基,因此基是不是 一个潜在构造的子对象,因此唯一适用于被删除的默认构造函数的规则不适用,因此不应删除它。编译器错了。

一个简单的解决方法(除了你已经提到的那些)是不声明 Derived::Derieved()根本。在这种情况下,它似乎是正确隐式生成的。

Adding the noexcept yields the error internal compiler error


这也是一个编译器错误。

关于c++ - GCC 上虚拟继承行为的奇怪默认空构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65287323/

相关文章:

c++ - OpenMP 卸载到 Nvidia 错误减少

c - 是自动的;有效的 C 翻译单元?

c++ - 将 std::shared_ptr 与 clang++ 和 libstdc++ 一起使用

c++ - 根据标记点对齐 2 张人脸图像

带模板的 C++ 共享库 : Undefined symbols error

c++ - Clion 未定义函数引用

c - 为什么 gcc 打印 "Segmentation fault: 11"?

_sync_val_compare_and_swap 可以返回除 int 之外的任何值吗?

C++17 std::variant 头文件 (clang 6.0.0)

c++ - 如何确定 bjam 中 cxxflags 的值?还是附加到它?