I have a class Iterator
, for which I have defined various operator overloads for equality testing (<
, <=
, >
, >=
, ==
and !=
) as friend functions. Prototype example:
friend bool operator<(const Iterator &A, const Iterator &B);
class RevIterator
inherits (virtually) from Iterator
. Naturally, I have had to overload the operators <
, <=
, >
and >=
for this class (as friend functions again). Prototype example:
friend bool operator<(const RevIterator &A, const RevIterator &B);
I also have a class ConstIterator
which inherits (virtually) from Iterator
, for which I have not defined more operator overloads (they are meant to behave in the same way as for Iterator
).
Finally, I have a class ConstRevIterator
which inherits from RevIterator
and ConstIterator
, for which I have not defined any operator overloads.
Visual class hierarchy:
class Iterator {};
class RevIterator : virtual public Iterator {};
class ConstIterator : virtual public Iterator {};
class ConstRevIterator : public RevIterator, public ConstIterator {};
My assumption was that for the operator <
, for example, operating on two ConstRevIterator
s, the function available for one of the parent classes, RevIterator
(2nd func. prototype above) would be called, instead of the function for the grandparent class, Iterator
(1st func. prototype above).
In summary, what are the rules for which function gets called on a reference to a 'grandchild' object, when there are functions available for its parent and grandparent classes?
Your assumption seems correct. You may find rules of overload resolution here https://en.cppreference.com/w/cpp/language/overload_resolution
Here is the part concerning your question:
- If Mid is derived (directly or indirectly) from Base, and Derived is derived (directly or indirectly) from Mid
a) Derived* to Mid* is better than Derived* to Base*
b) Derived to Mid& or Mid&& is better than Derived to Base& or Base&&
c) Base::* to Mid::* is better than Base::* to Derived::*
d) Derived to Mid is better than Derived to Base
e) Mid* to Base* is better than Derived* to Base*
f) Mid to Base& or Base&& is better than Derived to Base& or Base&&
g) Mid::* to Derived::* is better than Base::* to Derived::*
h) Mid to Base is better than Derived to Base
I also produced some code to verify it: https://godbolt.org/z/bc47dzxvY