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