基础构造函数和派生构造函数之间的歧义

时间:2015-06-12 01:40:10

标签: c++ c++11

我设计了以下代码片段来显示我的问题(原始问题更复杂):

#include <string>

struct A
{
  A(int, int) {}

  A(int p1 = 0, std::string p2 = "", int p3 = 0) {} // string for breaking ambiguity with previous ctor

  // There are a lot more of constructors for A class 
};

struct B : public A
{
  using A::A; // I want to inherit many base constructors in order to save work

  // But I need this particular constructor and it should override the
  // equivalent base constructor
  B(int p1 = 0, std::string p2 = "", int p3 = 0) {}
};

int main(int argc, char *argv[])
{
  B b(1); // gives "error: call to constructor of 'B' is ambiguous", what
      // of course is true, but I would want to inherit the other
      // base constructors. If I comment using A::A ==> this line compiles

  B b2(2, 3); // But if I comment using A::A ==> this line does not compile
}

所以,我的问题是:有没有办法打破这种歧义而不隐藏其他许多具有基类的构造函数?

提前致谢

2 个答案:

答案 0 :(得分:6)

当前继承的构造函数规范是......有些搞砸了。继承A(int p1 = 0, std::string p2 = "", int p3 = 0)构造函数隐式声明了三个签名:B(int)B(int, std::string)B(int, std::string, int),由于B的构造函数声明,其中只有最后一个被禁止。

N4429,一个修复当前规范的许多问题的提案,在上次委员会会议上通过了设计审查,如果通过,将解决您的问题。

解决方法是在B中编写一组委托构造函数,而不是使用默认参数:

  B() : B(0) {}
  B(int p1) : B(p1, "") {}
  B(int p1, std::string p2) : B(p1, std::move(p2), 0) {}
  B(int p1, std::string p2, int p3) {}

这会抑制从继承该基类构造函数声明的所有三个签名。

答案 1 :(得分:2)

如果定义派生类构造函数,则应在初始化列表中调用基类构造函数,如下所示:

struct B : public A
{
 // using A::A; // I want to inherit many base constructors in order to save work

  // But I need this particular constructor and it should override the
  // equivalent base constructor
  B(int p1 = 0, int p2 = 0, int p3 = 0):A(p1,p2,p3) {}
};

请注意,您不需要使用using语句来解决派生类中的歧义using A::A;。当您公开派生时,您将获得基类的所有公共和受保护组件在派生类中可用。

DEMO:http://coliru.stacked-crooked.com/a/52451127e54c8591