下标操作符的C++继承规则
问题描述:
我对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); }
};
因为我可能从父很多地方继承,它是坏的维护必须手动指定这样的功能。感谢您的想法。
答
避免两件事情在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
总是有'使用Parent :: operator []',但是你仍然必须在每个类中编写它。 –
重载解析一旦找到具有所需名称的候选人,就会停止。所以它会看到'Child :: operator [](B)'并停止寻找额外的重载,所以它永远不会看到一个采用'A'的版本。如果你像@JamesRoot所建议的那样'使用Parent :: operator []',它会将所有额外的重载带入'Child'的范围,所以重载将按照你的期望工作。 – 0x5453
什么让你觉得这个问题不同,只是因为它是下标运算符?修改你的代码使用一个叫做'f'的普通函数,你会遇到同样的编译错误。 –