Перегрузки унаследованных функций-членов

Могут ли методы перегрузки класса, которые также существуют в общепринятом интерфейсе? Кажется, что это однозначно и полезно, но компиляторы (VC, Intel, GCC) жалуются, по крайней мере, на мое строительство. Ниже приведен пример игрушек. Унаследованная функция отскока() имеет две явные перегрузки, но это не будет скомпилировано. Если вы переименуете метод отскока() в любом классе, он отлично работает, но если у них есть одно и то же имя функции-члена (даже если они перегружены разными типами аргументов!), Вы получаете фатальную ошибку "слишком мало аргументов для вызова функции".

Обходной путь тривиален (я просто переименую методы), но я просто пытаюсь понять, если это ограничение на С++ (и почему оно было бы).


#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

Вы можете сделать три вещи:

1. Показывать метод базового класса

Добавьте using в объявление Node:

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

2. Явно ссылаюсь на метод базового класса

Используйте пространство имен Bound:

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

3. Определить/переопределить все перегрузки в производном классе

Передайте реализацию базовому классу (если это сделано в заголовке, не должно быть никакого штрафа благодаря inlining):

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

Дополнительная информация: https://isocpp.org/wiki/faq/strange-inheritance#overload-derived

Ответ 2

Когда вы объявляете метод в подклассе с тем же именем, но с другой подписью, он фактически скрывает версию от родителя.

Вы можете ссылаться на него конкретно как Bound:: rebound (...) или использовать ключевое слово using.

Смотрите здесь

Ответ 3

Это называется скрытием функции родительского элемента. Вы можете явно вызвать его (через Bound::rebound(left, right), как сказал @Ates Goral), или вы можете добавить using Bound::rebound в определение класса Node.

Подробнее см. http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9.