Перегрузки унаследованных функций-членов - PullRequest
14 голосов
/ 23 января 2009

Может ли класс перегружать методы, которые также существуют в публично унаследованном интерфейсе? Кажется, это однозначно и полезно, но компиляторы (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 ]

22 голосов
/ 23 января 2009

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

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#overload-derived

2 голосов
/ 23 января 2009

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

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

См. здесь

1 голос
/ 23 января 2009

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

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

...