Я пытаюсь написать класс C ++, который имеет несколько перегруженных методов:
class Output
{
public:
static void Print(bool value)
{
std::cout << value ? "True" : "False";
}
static void Print(std::string value)
{
std::cout << value;
}
};
Теперь допустим, что я вызываю метод следующим образом:
Output::Print("Hello World");
это результат
Правда
Итак, почему, когда я определил, что метод может принимать логическое значение и строку, он использует логическую перегрузку, когда я передаю не логическое значение?
РЕДАКТИРОВАТЬ: я пришел из среды C # / Java, так что совершенно новый для C ++!
"Hello World"
строковый литерал типа «массив из 12 const char
«который может быть преобразован в» указатель на const char
«который в свою очередь может быть преобразован в bool
, Это именно то, что происходит. Компилятор предпочитает это использованию std::string
Конверсионный конструктор.
Последовательность преобразования, включающая конструктор преобразования, называется определяемая пользователем последовательность преобразования. Преобразование из "Hello World"
к bool
это стандартная последовательность преобразования. Стандарт гласит, что стандартная последовательность преобразования всегда лучше, чем определенная пользователем последовательность преобразования (§13.3.3.2 / 2):
стандартная последовательность преобразования (13.3.3.1.1) является лучшей последовательностью преобразования, чем определяемая пользователем последовательность преобразования или многоточечная последовательность преобразования
Этот анализ «лучшей последовательности преобразования» выполняется для каждого аргумента каждой жизнеспособной функции (и у вас есть только один аргумент), и лучшая функция выбирается разрешением перегрузки.
Если вы хотите убедиться, что std::string
версия называется, нужно дать std::string
:
Output::Print(std::string("Hello World"));
FWIW, он может быть адресован таким образом (если шаблоны могут быть использованы), если вы не хотите добавлять перегрузки для const char*
,
#include <iostream>
#include <string>
#include <type_traits>
template <typename Bool,
typename T = std::enable_if_t<std::is_same<Bool, bool>{}>>
void foo(Bool)
{
std::cerr << "bool\n";
}
void foo(const std::string&)
{
std::cerr << "string\n";
}
int main()
{
foo("bar");
foo(false);
}
Не знаю, почему никто не опубликовал это, но вы можете добавить еще одну перегрузку, которая преобразует из const char * в std :: string для вас. Это избавляет абонента от необходимости беспокоиться об этом.
class Output
{
public:
static void Print(bool value)
{
std::cout << value ? "True" : "False";
}
static void Print(std::string value)
{
std::cout << value;
}
// Just add the override that cast to std::string
static void Print(const* char value)
{
Output::Print(std::string(value));
}
};