I have a question regarding the subscript operator, overloading, and inheritance in C++. I'm pretty sure that if you have a parent class with multiple function overloads, it is possible for the child to override just one of the functions and inherit the rest. The same does not seem to apply to the subscript operator. (I made a bad assumption. It is really no different than any other function.) Consider the following code:
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()];
}
I would expect for it to use the subscript operator from the parent instead of causing an error. Is it possible to inherit some overloaded subscript operators from the parent and override others? If not, is there any better solution than doing:
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); }
};
Since I potentially inherit from the parent many places, and it is bad for maintenance to have to manually specify functions like this. Thanks for your ideas.
Avoid two things in C++:
Keep your base-class overloaded operators non-virtual and have them delegate to private virtual functions with distinct names.
Here is an example:
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()];
}
This approach, also known as the Non-Virtual Interface Idiom, represents a nice separation of concerns between the clients of the base class and the implementors of derived classes. It also solves your compilation problem as a side effect.