3

测试显示了一个奇怪的行为(c++14, g++ 4.9.1, clang 3.5.5):

把它们加起来:

  • 如果B没有提供它可以使用的其他构造函数A::A()
  • ifB提供了它不能使用的其他构造函数A::A(),但它使用了A::A(whatever arguments),这是出乎意料的行为(至少对我而言)。

设置 1:

struct A {
  A() {};
  A(int) {}; // with or without this overload the result are the same
};

struct B : A {
  using A::A;
};

B b0{}; // OK

设置 2:

struct A {
  A() {}; // with a default constructor instead (empty class A)
          // the results are the same
};

struct B : A {
  using A::A;
  B(int){}
};

B b0{}; // no matching constructor
B b1{24}; // OK

设置 3:

struct A {
  A() {};
  A(int) {};
};

struct B : A {
  using A::A;
  B(int, int){}
};

B b0{}; // no matching constructor
B b1{24}; // OK
B b2{24, 42}; // OK

为什么会发生这种情况以及如何“修复”它。

4

1 回答 1

3

我不能告诉你这样做的理由,但我至少可以告诉你这是标准规定的:

[C++11: 12.9/3]: 对于候选继承构造函数集合中的每个非模板构造函数,除了没有参数的构造函数或具有单个参数的复制/移动构造函数之外,构造函数被隐式声明为具有相同的构造函数特征,除非存在用户声明的构造函数在出现using-declaration的类中具有相同的签名。[..]

由于 defaultB()调用 default A(),您可以像这样“修复”它:

struct B : A
{
   B() = default;

   using A::A;
   B(int, int){}
};

现场演示

原始提案(n2540) 中的以下措辞表明,此修复的易用性和对称性或多或少是该决定背后的驱动因素,尽管我仍然觉得这有点不令人满意。那好吧。

复制和默认构造函数不会被转发,遵循隐式声明复制/默认构造函数的现有规则。

于 2015-02-24T19:49:15.830 回答