继承构造函数并提供新的重载:没有参数基础构造函数似乎不参与重载解析

时间:2015-02-24 19:34:22

标签: c++ overloading c++14 inheriting-constructors

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

总结一下:

  • 如果B未提供其他构造函数,则可以使用A::A()
  • 如果B提供其他构造函数,则无法使用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

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

1 个答案:

答案 0 :(得分:3)

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

  

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

由于默认B()会调用默认的A(),因此您可以像这样“修复”它:

struct B : A
{
   B() = default;

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

live demo

以下wording from the original proposal(n2540)表明,此修复的简易性和对称性或多或少是决定背后的驱动因素,尽管我仍然觉得有些不满意。哦,好吧。

  

不转发复制和默认构造函数,推迟使用隐式声明复制/默认构造函数的现有规则。