C++ наследование и сокрытие имени

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

#include <iostream>

using namespace std ;

class Base {
public:
    void methodA() { cout << "Base.methodA()" << endl ;}
};

class Derived : public Base {
public:
    void methodA(int i) { cout << "Derived.methodA(int i)" << endl ;}
};

int  main()
{
  Derived obj;
  obj.methodA();
}

Компиляция этого кода с последней версией g++ выдает ошибку

no matching function for call to 'Derived::methodA()'

Именно из-за этой ошибки я наткнулся на Stackru, чтобы найти ответ. Но ни один из ответов не убедил меня. Сигнатуры двух методов не представляют никакой двусмысленности при их различении, компилятор должен иметь возможность подобрать метод в базовом классе. Просто закомментируйте

class Derived : public Base {
//public:
//    void methodA(int i) { cout << "Derived.methodA(int i)" << endl ;}
};

и код работает как положено. Это означает, что это просто имя функции-члена, чтобы скрыть одну и ту же функцию-член имени в базовом классе, и подпись не принимается во внимание, как если бы имена функций не были искажены (в этом случае искажение должно устранить любую неоднозначность). Кто-то еще написал в аналогичном вопросе, что это противоречит духу C++ (и, как я добавил, объектной ориентации), и я полностью согласен с ним. Это ограничение перегрузки функций, для которого я действительно не вижу никакой разумной причины.

Очевидно, вопрос закрыт, поэтому я не могу добавить ответ после прочтения ответов, кроме как путем редактирования моего первоначального вопроса. Я совершенно уверен (но я не в состоянии доказать это), что в старых компиляторах C++ код в моем первоначальном вопросе компилировался (и затем выполнялся) без проблем. Моя точка зрения заключается в том, что я действительно не вижу смысла в выборе языка (как он был назван в ответах). Компилятор, в этом случае, имеет всю информацию, чтобы предпринять правильные действия, и это то, что я ожидаю. В противном случае, похоже, что по выбору дизайна языка он был выбран без учета сигнатуры функций-членов, что звучит довольно странно. Я прочитал статью в "programmerinterview", указанной выше, но она не объясняет, что послужило причиной такого выбора дизайна языка (более того, "someFunction" в "GrandChildClass" в примере кода к концу этой статьи не переопределяет, как уже говорилось, функция-член класса с одинаковым именем: две функции-члена с одинаковыми именами имеют разные сигнатуры - так что это не переопределение).

3 ответа

Так устроен язык - имена во внутренних областях скрывают имена во внешних областях. Здесь производный класс действует как внутренняя область, а базовый класс - как внешняя область.

Тот факт, что функции будут считаться перегрузками, если они находятся в одной области, не имеет значения. Сокрытие работает на имена, а не на отдельные функции.

Вы можете переопределить значение по умолчанию, явно добавив имя к производному классу:

class Derived : public Base {
public:
    using Base::methodA;   // Now it is visible!

    void methodA(int i) { cout << "Derived.methodA(int i)" << endl ;}
};

Это означает, что это просто имя функции-члена, чтобы скрыть ту же функцию-член имени в базовом классе, и подпись не принимается во внимание

Правильный. Именно так был разработан язык. Мне не очень нравится эта особенность языкового дизайна. Но это хорошо задокументировано, и у вас нет выбора.

Я думаю, вы уже поняли. Это называется скрытием имени, и именно так создается язык. Но я не вижу в этом неудобства, так как в конечном итоге вы достаточно комфортно соглашаетесь с этим, когда проводите время с C++. Когда вы определяете не виртуальный метод с тем же именем, что и метод Base, он скрывает метод базового класса в классе Derived, поэтому вы получаете сообщение об ошибке для

obj.methodA();

Чтобы избежать скрытия методов базового класса в классе Derived, вы можете сделать:

obj.Base::methodA();

Для получения дополнительной информации: http://www.programmerinterview.com/index.php/c-cplusplus/c-name-hiding/

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