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

Ambiguity between base and derived constructors

本文关键字:构造函数 歧义 之间 派生      更新时间:2023-10-16

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

#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
}

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

提前致谢

当前的继承构造函数规范是...有点搞砸了。继承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) {}

这将禁止从继承该基类构造函数中声明的所有三个签名。

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

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; 。当您公开派生时,您将获得基类的所有公共和受保护组件将在派生类中可用。

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