Подтвердить что ты не робот

Перегрузка метода базового класса в производном классе

Я пытаюсь понять, почему следующий код не компилируется, по-видимому, решение зависит от конкретного объявления зависимости от метода_А в производном классе. Пожалуйста, обратитесь к следующему коду:

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)".

Какова техническая причина, которая мешает тому, чтобы производный класс знал свой базовый класс, реализует метод, который он пытается перегрузить? Я лучше понимаю, как в этом случае ведет себя компилятор/компоновщик.

4b9b3361

Ответ 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 приносит функцию базового класса в пространство имен дочернего класса, так как поведение по-умолчанию не делает этого по умолчанию.