Могу ли я переопределить только один метод в наследовании?

Мой C++ код выглядит следующим образом:

#include<iostream>
using namespace std;

class A
{
    public:
        virtual void f(int i)
        {
            cout << "A's f(int)!" << endl;
        }
        void f(int i, int j)
        {
            cout << "A's f(int, int)!" << endl;
        }
};

class B : public A
{
    public:
        virtual void f(int i)
        {
            cout << "B's f(int)!" << endl;
        }
};

int main()
{
    B b;
    b.f(1,2);
    return 0;
}

во время компиляции я получаю:

g++ -std=c++11 file.cpp 
file.cpp: In function ‘int main()’:
file.cpp:29:9: error: no matching function for call to ‘B::f(int, int)’
file.cpp:29:9: note: candidate is:
file.cpp:20:16: note: virtual void B::f(int)
file.cpp:20:16: note:   candidate expects 1 argument, 2 provided

Когда я попытался использовать переопределение после B (F), я получил ту же ошибку.

Возможно ли в C++ переопределить только 1 метод? Я искал пример кода, используя override который скомпилируется на моей машине и еще не нашел.

5 ответов

Решение

Вы переопределяете имя "f" как имя метода. Таким образом, любая перегрузка также будет отменена.

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

class B : public A
{
    public:
        using A::f;
        virtual void f(int i)
        {
            cout << "B's f(int)!" << endl;
        }
};

Проблема в том, что ваша виртуальная функция f() в классе B шкуры Aне виртуальная перегрузка с одинаковым именем. Вы можете использовать using декларация, чтобы привести его в сферу:

class B : public A
{
    public:
        using A::f;
    //  ^^^^^^^^^^^

        virtual void f(int i)
        {
            cout << "B's f(int)!" << endl;
        }
};

Вы укушены тем, как поиск имен работает в C++. Компилятор просматривает последовательные области, пока не найдет область с хотя бы одним элементом с соответствующим именем.

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

Однако вы можете получить его для поиска в классе родителя в этом случае:

class B : public A
{
    public:
        using A::f;
        virtual void f(int i)
        {
            cout << "B's f(int)!" << endl;
        }
};

На первый взгляд может показаться, что using Заявление может привести к двусмысленности. Например, с using A::f; теперь есть два f(int) функции, видимые в BСфера (A::f(int) а также B::f(int)). C++ имеет некоторые правила, чтобы покрыть это, так что если вы добавите (например) b.f(3); в mainusing A::f; на месте) вы все еще не получите двусмысленность - это позвонит b::f(int) как и следовало ожидать.

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

using A::f;

к определению вашего базового класса.

Хорошо для чтения:

В чем смысл, Предупреждение: Derived::f(char) скрывает Base::f(double)?

Да, можно переопределить только один метод класса, сделать его виртуальным. Не виртуальный будет затенен при объявлении в унаследованном классе.

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