Почему C++ не поддерживает перегрузку между областями?

Я полагаю, что лучший ответ уже дан здесь: почему переопределенная функция в производном классе скрывает другие перегрузки базового класса?

Но меня немного смущает, особенно с утверждением:

Чтобы переопределить это поведение, от пользователя требуется явное действие: первоначально переопределение унаследованного метода (ов) (в настоящее время не рекомендуется), теперь явное использование 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;
}

У меня есть два вопроса:

  1. Можно ли предположить, что по отношению к производному объекту класса int f(int i) Функция не существует вообще. Это не наследуется из-за сокрытия имени.

  2. Если мне нужно использовать эту функцию в производном классе, я должен снова определить ее в производном классе?

1 ответ

  1. Можно ли предположить, что по отношению к производному объекту класса функция int f(int i) вообще не существует. Это не наследуется из-за сокрытия имени.

Он наследуется, он просто... скрыт, его нельзя найти, если вы не укажете область действия ( поиск по неквалифицированному имени. Вы можете указать его явно с помощью оператора разрешения области действия :: ( уточненный поиск имени):

dp->Base::f(3);
  1. Если мне нужно использовать эту функцию в производном классе, я должен снова определить ее в производном классе?

Как сказано в цитируемом ответе, вы можете сделать это с "явным использованием using-декларации".

class Derived : public Base
{
public:
    using Base::f;
    ...
};

РЕДАКТИРОВАТЬ (для дополнительных вопросов из комментария)

  1. Если это имя скрыто, значит, я могу объявить его снова? То же имя, те же параметры?

Да, ты можешь. Это все еще имя, скрывающее.

  1. Если да, то что, если я также добавил using Base::f вместе с новой декларацией? Это приведет к двойному определению?

Нет, это не двойное определение. Использование объявления просто вводит имя в область производного класса. И функция-член, объявленная в производном классе, будет скрывать ту, что была введена из базового класса, но она по-прежнему скрывает имя (Обратите внимание, что вы все еще можете вызвать один из базового класса по dp->Base::f(3);.)

Если у производного класса уже есть член с тем же именем, списком параметров и квалификациями, член производного класса скрывает или переопределяет (не конфликтует) член, представленный в базовом классе.

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