基类构造函数对派生类C++不可见

Base class constructor not visible to derived class C++

本文关键字:C++ 构造函数 派生 基类      更新时间:2023-10-16

我正在用C++编写一个玩具正则表达式引擎作为学习练习,但我遇到了编译器错误。下面是实现不同表达式子类型的类的定义:

// ***************************************************************
// ***************************************************************
  class RegexExpression {
  public:
    virtual RegexResult match(std::string);
  };
// ***************************************************************
  class RegexTerm : public virtual RegexExpression {
  public:
    RegexTerm(char c) : _matchChar(c) {}
    RegexResult match(std::string);
  private:
    char _matchChar;
  };
// ***************************************************************
  class RegexNil : public virtual RegexExpression {
  public:
    RegexResult match(std::string);
  };
// ***************************************************************
// ***************************************************************
  class RegexBinaryExpression : public virtual RegexExpression {
  public:
    RegexBinaryExpression
    (RegexExpression &lhs, RegexExpression &rhs) :
      _lhs(lhs), _rhs(rhs) {}
  protected:
    RegexExpression _lhs;
    RegexExpression _rhs;

  };
// ***************************************************************
  class RegexOr : public RegexBinaryExpression {
  public:
    RegexResult match(std::string);
  };
// ***************************************************************
  class RegexAnd : public RegexBinaryExpression {
  public:
    RegexResult match(std::string);
  };

但是,当我尝试实例化正则表达式时,例如:

RegexOr regex(RegexTerm('a'), RegexNil());

然后我收到一个编译器错误,告诉我来自 RegexBinaryExpression 的 2 参数构造函数不可见。

如果我在正则表达式中显式定义构造函数,例如:

RegexOr(RegexExpression &l, RegexExpression &r) : RegexBinaryExpression(l, r) {}

然后我被告知RegexNil不能转换为RegexExpression。

我在这里做错了什么?

至少

在 C++11 之前,您肯定必须在 RegexOr 中自己实现构造函数。但是,您将其实现为采用非常量引用参数,然后尝试从临时引用参数绑定该参数,这是语言禁止的。

而是通过 const 引用(甚至可能按值)获取参数:

RegexBinaryExpression(const RegexExpression &lhs, const RegexExpression &rhs)
: _lhs(lhs)
, _rhs(rhs)
{}
RegexOr(const RegexExpression &l, const RegexExpression &r) : RegexBinaryExpression(l, r) {}

不能将临时对象传递给非常量引用参数。要使其编译,您需要将参数更改为 const 引用(或按值)。

不过你有一个更大的问题。将参数复制到 RegexBinaryExpression 的成员时,它们将存储为 RegexExpression 对象,而不是派生对象。有关派生类型的信息将丢失。这称为对象切片。

您需要动态分配正则表达式对象,并将指向它们的指针存储在类中。我会推荐智能指针。您还可以将正则表达式对象的类型存储在类、模板参数中,而不是继承层次结构中。这可能更难实现,并且有一些缺点。