2017-05-12 36 views
3

我对C++中的下标操作符,重载和继承有疑问。 我很确定,如果您有一个具有多个函数重载的父类,那么子类可能只覆盖其中一个函数并继承其他函数。这似乎不适用于下标算子。 (我做了一个错误的假设这是真的没有比其他任何功能不同。)请看下面的代码:下标操作符的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); } 
}; 

因为我可能从父很多地方继承,它是坏的维护必须手动指定这样的功能。感谢您的想法。

+2

总是有'使用Parent :: operator []',但是你仍然必须在每个类中编写它。 –

+1

重载解析一旦找到具有所需名称的候选人,就会停止。所以它会看到'Child :: operator [](B)'并停止寻找额外的重载,所以它永远不会看到一个采用'A'的版本。如果你像@JamesRoot所建议的那样'使用Parent :: operator []',它会将所有额外的重载带入'Child'的范围,所以重载将按照你的期望工作。 – 0x5453

+1

什么让你觉得这个问题不同,只是因为它是下标运算符?修改你的代码使用一个叫做'f'的普通函数,你会遇到同样的编译错误。 –

回答

4

避免两件事情在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,表示的基类的客户端和派生类的实现者之间的关注一个很好的分离。它也可以解决您的编译问题,作为一个副作用。

+0

我离开了虚拟析构函数以简化示例,但是,从技术上讲它应该在那里(我将它添加到问题中)。这是一个有效的想法,但我会和James Root的想法一起去做。谢谢。 – Mark