Компилятор C ++ (cl) не видит родительский виртуальный метод с тем же именем дочернего метода - PullRequest
0 голосов
/ 21 октября 2018

У меня есть код C ++, использующий наследование и переопределение функций одновременно, вот код:

#include <iostream>
#include <string>

using namespace std;

class Parent
{
    protected:
        virtual void G() const = 0;
    public:
        virtual void G(const string& s) const final { G(); }
};

class Child : public Parent
{
    protected:
        virtual void G() const override { cout<<"Child G"; }
};

int main()
{
    Child *c = new Child();
    c->G("test");
    return 0;
}

При компиляции я получил ошибку: Child::G: function does not take 1 arguments.Но когда я использую родительский указатель, вот так:

Parent *c = new Child();

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

Что плохого в использовании одного и того же имени (G) для обоих методов?

Ответы [ 2 ]

0 голосов
/ 21 октября 2018

Исправление для этого действительно состоит в том, чтобы ввести метод Parent в область действия класса Child с объявлением using, как любезно указывает @Jans.Что касается почему , то это просто вопрос того, как компилятор выполняет поиск по областям при поиске метода, соответствующего вызову вашей функции.Ниже описывается, что происходит:

  • в Child *c = new Child(); c->G("test");, компилятор видит вызов некоторого метода G для объекта типа Child.Затем он ищет область действия Child, чтобы найти совпадение.
  • Компилятор при исследовании области действия Child видит только Child::G() const.Он не см. Parent::G(const std::string&) const, который, даже если вы хотите, чтобы он был включен посредством наследования, находится в другой области действия .В некотором смысле, Child::G является тенями Parent::G.Без подходящего соответствия компилятор продолжил бы поиск в области действия Parent.
  • Таким образом, компилятор рад, что нашел Child::G.Однако эта функция не принимает аргументов, и вы пытались вызвать ее с помощью "test".В этом случае вызов функции завершается неудачно из-за несоответствия параметров.

Как уже говорилось, вам нужно перевести Parent::G в ту же область, что и Child::G, чтобы перегрузка произошла как задумано, с using Parent::G внутри тела Child.

Источник: https://isocpp.org/wiki/faq/strange-inheritance#overload-derived

0 голосов
/ 21 октября 2018

Вам необходимо ввести родительского члена в ребенка с помощью объявления using:

class Child : public Parent
{
    protected:
        virtual void G() const override { cout<<"Child G"; }
    public:
        using Parent::G;
};
...