【问题标题】:Initializing base class const member in most derived class在大多数派生类中初始化基类 const 成员
【发布时间】:2019-01-25 09:06:12
【问题描述】:

在下面的代码中,我在最派生类Grandchild 中初始化Base 类的成员const

class Base {
public:
    Base(int x_) : x(x_) {}

private:
    const int x;
};

class Child : public virtual Base {
public:
    virtual ~Child() = 0;
};

class Grandchild : public virtual Child {
public:
    Grandchild() : Base(42) {}
};

Child::~Child() {}

int main() {
    Grandchild gc;
}

在虚拟继承的情况下,Base 类的构造函数由最派生的类调用。因此,我希望代码能够成功编译。

clang 4.0 编译成功,而 gcc 4.9.2 发出以下错误:

 In constructor 'Grandchild::Grandchild()': 
16:27: error: use of deleted function 'Child::Child()' 
9:7: note: 'Child::Child()' is implicitly deleted because the default definition would be ill-formed: 
9:7: error: no matching function for call to 'Base::Base()' 
9:7: note: candidates are: 3:5: note: Base::Base(int) 
3:5: note: candidate expects 1 argument, 0 provided 
1:7: note: constexpr Base::Base(const Base&) 
1:7: note: candidate expects 1 argument, 0 provided 
1:7: note: constexpr Base::Base(Base&&) 
1:7: note: candidate expects 1 argument, 0 provided 

标准对此有何规定?

【问题讨论】:

  • @Ron 我不明白,使用虚拟继承有什么问题吗?无论如何,我这样做是因为我想在最派生的类中初始化基类成员。
  • 只有在选择 C++11 时才会出现错误,使用 C++14 可以很好地实时编译:godbolt.org/z/nZdAln 也许您需要告诉您的编译器使用 C++14?跨度>
  • 这就是虚拟继承类一直以来的工作方式。最派生类负责构建所有虚拟超类。
  • 当然是 gcc 错误。 [class.base.init] 中有一条注释阐明了应该发生的情况:抽象类([class.abstract])永远不是最派生的类,因此它的构造函数永远不会初始化虚拟基类,因此对应的mem-initializers 可以省略。 Child 就是这种情况。如果Child 的虚析构函数被移除,那么所有编译器都会拒绝该代码并出现同样的错误。

标签: c++ constructor c++14 language-lawyer virtual-inheritance


【解决方案1】:

C++ 标准似乎发生了变化,明确了virtual 基类生成的构造函数的要求。见CWG257。据我理解这篇文章你的情况应该被允许。在改变之前情况还不清楚。

此更改在 2009 年 10 月被投票纳入工作文件,即它应该适用于使用 C++11 进行编译。

【讨论】:

  • 以前的情况是这样的构造函数显然是不正确的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 2010-11-10
  • 1970-01-01
  • 2017-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多