Почему компилятор C++ (VS2013) выбирает неправильную функцию?
Первый случай
#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);