【问题标题】:C++ Inheritance Rules for Subscript Operator下标运算符的 C++ 继承规则
【发布时间】:2017-10-12 02:09:47
【问题描述】:

我有一个关于 C++ 中的下标运算符、重载和继承的问题。 我很确定,如果您有一个具有多个函数重载的父类,则子类可以仅覆盖其中一个函数并继承其余函数。这似乎不适用于下标运算符。(我做了一个错误的假设。它实际上与任何其他函数没有什么不同。)考虑以下代码:

struct A {};
struct B {};

struct Parent
{
   virtual ~Parent() {}
   virtual int operator[](A index) { return -1; }
   virtual int operator[](B index) { return -2; }
};

struct Child : public Parent
{
   virtual int operator[](B index) override { return -3; }
};

int main()
{
   // error: no match for 'operator[]' (operand types are 'Child' and 'A')
   return Child()[A()]; 
}

我希望它使用父级的下标运算符而不是导致错误。是否可以从父级继承一些重载的下标运算符并覆盖其他的?如果没有,有没有比这样做更好的解决方案:

struct Child : public Parent
{
    virtual int operator[](B index) override { return -3; }
    // Force it to use the parent method
    virtual int operator[](A index) override { return Parent::operator[](index); }
};

由于我可能从父级继承了许多地方,因此必须手动指定这样的功能对维护是不利的。感谢您的想法。

【问题讨论】:

  • 总是有using Parent::operator[],但你还是要在每个班级里写。
  • 一旦找到任何具有所需名称的候选者,重载解析就会停止。所以它将看到Child::operator[](B) 并停止寻找额外的重载,所以它永远不会看到采用A 的版本。如果您像@JamesRoot 建议的那样执行using Parent::operator[],它将把所有额外的重载带入Child 的范围内,因此重载将按您的预期工作。
  • 是什么让你觉得这个问题是不同的,只是因为它是下标运算符?修改您的代码以使用名为f 的普通函数,您将遇到相同的编译错误。
  • @ChristianHackl,是的。我做了一个错误的假设。这是所有函数的 C++ 限制。
  • @JamesRoot(和@0x5453),我喜欢这个主意。我会用它。谢谢。

标签: c++ inheritance overloading operator-keyword subscript


【解决方案1】:

在 C++ 中避免两件事:

  • 混合重载和覆盖。
  • 公共虚函数(如果它不是析构函数)。

让您的基类重载运算符保持非虚拟,并让它们委托给具有不同名称的私有虚拟函数。

这是一个例子:

struct A {};
struct B {};

struct Parent
{
   virtual ~Parent() {}
   int operator[](A index) { return withA(index); }
   int operator[](B index) { return withB(index); }
private:
   virtual int withA(A index) { return -1; }
   virtual int withB(B index) { return -2; }
};

struct Child : public Parent
{
private:
   virtual int withB(B index) override { return -3; }
};

int main()
{
   return Child()[A()]; 
}

这种方法,也称为Non-Virtual Interface Idiom,代表了基类的客户和派生类的实现者之间的良好分离。作为副作用,它还解决了您的编译问题。

【讨论】:

  • 我关闭了虚拟析构函数以简化示例,但是是的,从技术上讲它应该存在(我将它添加到问题中)。这是一个有效的想法,但我会同意 James Root 的想法。谢谢。
猜你喜欢
  • 2015-11-19
  • 1970-01-01
  • 2011-12-05
  • 2021-06-07
  • 2012-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多