Overloads of inherited member functions

2019-02-08 08:04发布

问题:

Can a class overload methods that also exist in the publicly inherited interface? It seems like this is unambiguous and useful, but compilers (VC, Intel, GCC) all complain, at least by my construction. Below is a toy example. The inherited rebound() function has two clear overloads, yet this will not compile. If you rename the rebound() method in either class, it works fine, but if they share the same member function name (even though they're overloaded with different argument types!) you get a fatal error of "too few arguments to function call."

The workaround is trivial (I'll just rename the methods) but I'm just trying to understand if this is a C++ restriction (and why it would be).


#include 
class Bound {
public:
  Bound() : x0(0.0), x1(0.0) {};
  Bound(double x) : x0(x), x1(x) {};
  double width() const {return x1-x0;}
  void rebound(const Bound *a, const Bound *b);
private:
  double x0, x1;
};

void Bound::rebound(const Bound *a, const Bound *b)
{
  if (a && b) {
    x0=std::min(a->x0, b->x0);
    x1=std::max(a->x1, b->x1);
  }
}

class Node : public Bound {
public:
  Node(double x) : Bound(x), left(0), right(0) {};
  Node(Node *a, Node *b) : left(a), right(b) {rebound();}
  void rebound() { rebound(left, right); }
private:
  Node *left;
  Node *right;
};


int main() {
  Node A(1.0);
  Node B(2.0);
  Node C(&A, &B);
}

回答1:

You can do three things:

1. Unhide the base class method

Add a using in the Node declaration:

using Bound::rebound;
void rebound() { rebound(left, right); }

2. Explicitly refer to the base class method

Use the Bound namespace:

void rebound() { Bound::rebound(left, right); }

3. Define/redefine all overloads in the derived class

Delegate the implementation to the base class (if this is done in the header, there shouldn't be any penalty thanks to inlining):

void rebound(const Bound *a, const Bound *b) { Bound::rebound(a, b); };
void rebound() { rebound(left, right); }

More info: https://isocpp.org/wiki/faq/strange-inheritance#overload-derived



回答2:

When you declare a method in the subclass with the same name but a different signature, it actually hides the version from the parent.

You could refer to it specifically as Bound::rebound(...) or use the using keyword.

See here



回答3:

This is called hiding the parent member function. You can explicitly call it (by Bound::rebound(left, right) as @Ates Goral said) or you can add a using Bound::rebound in your Node class definition.

See http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9 for more info.