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

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

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


#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);
}

3 ответа

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

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

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

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

2. Явно обратитесь к методу базового класса

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

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

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

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

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

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

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

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

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

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

См. http://www.parashift.com/c++-faq-lite/strange-inheritance.html для получения дополнительной информации.

Другие вопросы по тегам