Почему компилятор C++ (VS2013) выбирает неправильную функцию?

  1. Первый случай

    #include <iostream>
    class A
    {
    public:
        virtual void Write(int i)
        {
            std::wcout << L"Write(int) is called" << std::endl;
        }
        virtual void Write(wchar_t c)
        {
            std::wcout << L"Write(wchar_t) is called" << std::endl;
        }
    };
    int _tmain(int argc, wchar_t* argv[])
    {
        A *p = new A();
        int i = 100;
        p->Write(i);
        return 0;
    }
    

Работает отлично.
Результаты программы
Запись (int) называется

2. Второй случай.
Просто переместите первую функцию в базовый класс:

#include <iostream>
class Base
{
public:
   virtual void Write(int i)
   {
       std::wcout << L"Base::Write(int) is called" << std::endl;
   }
};
class Derived: public Base
{
public:
    virtual void Write(wchar_t c)
    {
        std::wcout << L"Derived::Write(wchar_t) is called" << std::endl;
    }
};
int _tmain(int argc, wchar_t* argv[])
{
    Derived *p = new Derived();
    int i = 100;
    p->Write(i);
    return 0;
}

Результаты программы
Derived::Write(wchar_t) называется
Но я ожидал, что "Base::Write(int) называется"
Что не так во втором случае?

2 ответа

Решение

Ваш компилятор прав.

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

Ты можешь использовать using чтобы импортировать его в область производного класса, сделайте перегрузку работающей, как вы ожидаете.

class Derived: public Base
{
public:
    using Base::Write;
    virtual void Write(wchar_t c)
    {
        std::wcout << L"Derived::Write(wchar_t) is called" << std::endl;
    }
};

РЕДАКТИРОВАТЬ

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

Смотрите поиск имени

Я предполагаю, что это потому, что программа находит "более новую" версию функции, которая верна с неявным преобразованием, поэтому она не ищет "лучшую" функцию для вызова в родительском классе. Я бы предложил: 1) избегать перегрузки / переопределения функций с параметрами, которые являются взаимозаменяемыми. 2) Если вы действительно хотите, чтобы вызывался Derived:: Write, используйте:

 p->Derived::Write(i);
Другие вопросы по тегам