Я считаю, что лучший ответ уже дан здесь: Почему переопределенная функция в производном классе скрывает другие перегрузки базового класса?
Но меня немного смущает, особенно с утверждением:
Чтобы переопределить это поведение, от пользователя требуется явное действие: первоначально переопределение унаследованного метода (ов) (в настоящее время не рекомендуется), теперь явное использование using-декларации.
Предположим, у меня есть следующая программа:
#include <iostream>
using namespace std;
class Base
{
public:
int f(int i)
{
cout << "f(int): ";
return i+3;
}
};
class Derived : public Base
{
public:
double f(double d)
{
cout << "f(double): ";
return d+3.3;
}
};
int main()
{
Derived* dp = new Derived;
cout << dp->f(3) << '\n';
cout << dp->f(3.3) << '\n';
delete dp;
return 0;
}
У меня есть два вопроса:
Могу ли я предположить, что объект производного класса w.r.t int f(int i)
Функция не существует вообще. Это не наследуется из-за сокрытия имени.
Если мне нужно использовать эту функцию в производном классе, я должен снова определить ее в производном классе?
- Могу ли я предположить, что при производном объекте класса w.r.t функция int f (int i) вообще не существует. Это не наследуется из-за сокрытия имени.
Это является по наследству, это просто … скрытый, не может быть найден, если вы не указали область действия (поиск безусловного имени. Вы можете указать это явно с помощью оператора разрешения области ::
(поиск подходящего имени):
dp->Base::f(3);
- Если мне нужно использовать эту функцию в производном классе, я должен снова определить ее в производном классе?
Как сказано в цитируемом ответе, вы можете сделать это с «явным использованием using-декларации».
class Derived : public Base
{
public:
using Base::f;
...
};
РЕДАКТИРОВАТЬ (для дополнительных вопросов из комментария)
- Если это имя скрыто, значит, я могу объявить его снова? То же имя, те же параметры?
Да, ты можешь. Это все еще имя, скрывающее.
- Если да, то что, если я также добавил
using Base::f
вместе с новой декларацией? Это приведет к двойному определению?
Нет, это не двойное определение. Использование декларации просто вводит имя в область производного класса. И функция-член, объявленная в производном классе, будет скрывать ту, что была введена из базового класса, но она по-прежнему скрывает имя. (Обратите внимание, что вы все еще можете вызвать один из базового класса по dp->Base::f(3);
.)
Если у производного класса уже есть член с тем же именем, списком параметров и квалификациями, член производного класса скрывает или переопределяет (не конфликтует) член, представленный в базовом классе.
Других решений пока нет …