Перегрузка метода базового класса в производном классе
Я пытаюсь понять, почему следующий код не компилируется, по-видимому, решение зависит от конкретного объявления зависимости от метода_А в производном классе.
Пожалуйста, обратитесь к следующему коду:
class Base
{
public:
void method_A(int param, int param2)
{
std::cout << "Base call A" << std::endl;
}
};
//does not compile
class Derived : public Base
{
public:
void method_A(int param)
{
std::cout << "Derived call A" << std::endl;
}
};
//compiles
class Derived2 : public Base
{
public:
using Base::method_A; //compile
void method_A(int param)
{
std::cout << "Derived call A" << std::endl;
}
};
int main ()
{
Derived myDerived;
myDerived.method_A(1);
myDerived.method_A(1,2);
Derived2 myDerived2;
myDerived2.method_A(1);
myDerived2.method_A(1,2);
return 0;
}
"test.cpp", (S) Неправильное количество аргументов указано для "Derived:: method_A (int)".
Какова техническая причина, которая мешает тому, чтобы производный класс знал свой базовый класс, реализует метод, который он пытается перегрузить?
Я лучше понимаю, как в этом случае ведет себя компилятор/компоновщик.
Ответы
Ответ 1
Его называют Сокрытие имени.. Когда вы определяете не виртуальный метод с тем же именем, что и метод Base, он скрывает метод базового класса в классе Derived, поэтому вы получаете ошибку для
myDerived.method_A(1,2);
Чтобы избежать скрытия методов класса Base в классе Derived, используйте ключевое слово, как в классе Derived2.
Также, если вы хотите сделать это, вы можете сделать это эксплицитно
myDerived.Base::method_A(1,2);
Ознакомьтесь с этим для лучшего объяснения, почему скрыть скрытие имени.
Ответ 2
Хорошо, для одного вы звоните
myDerived.method_A(1,2);
с двумя аргументами, тогда как как в базе, так и в производном объявлен метод принятия только одного аргумента.
Secodnly, вы ничего не игнорируете, потому что метод_А не является виртуальным. Вы перегружаетесь.
Ответ 3
Если вы намерены переопределить void Base::method_A(int param, int param2)
, тогда вы должны пометить его виртуальным в базовом классе:
virtual void method_A(int param, int param2)
Любая функция, переопределяющая это, должна иметь одинаковые параметры и почти тот же тип возврата ( "почти" слабо означает, что разные типы возвращаемых данных должны быть связаны с полиморфизмом, но в большинстве случаев он должен иметь идентичный тип возврата).
Все, что вы сейчас делаете, это перегрузка функции в базовом классе. Ключевое слово using
приносит функцию базового класса в пространство имен дочернего класса, так как поведение по-умолчанию не делает этого по умолчанию.