наследование — почему компилятор 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) называется»
Что не так во втором случае?

3

Решение

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

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

Ты можешь использовать 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 никогда не будет рассматриваться для разрешение перегрузки, даже если версия базового класса здесь более уместна.

Увидеть Поиск имени

4

Другие решения

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

 p->Derived::Write(i);
0

По вопросам рекламы [email protected]