51

我正在尝试编写一个具有一些重载方法的 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++ 很陌生!

4

4 回答 4

63

"Hello World"是“12 数组const char”类型的字符串文字,可以转换为“指向”的“指针”,而“指针const char”又可以转换为bool. 这正是正在发生的事情。编译器更喜欢使用std::string' 的转换构造函数。

涉及转换构造函数的转换序列称为用户定义的转换序列。从"Hello World"到 a的转换bool是一个标准的转换序列。该标准规定标准转换序列始终优于用户定义的转换序列(第 13.3.3.2/2 节):

标准转换序列 (13.3.3.1.1) 是比用户定义的转换序列或省略号转换序列更好的转换序列

这种“更好的转换序列”分析是针对每个可行函数的每个参数进行的(并且您只有一个参数),并且通过重载决议选择更好的函数。

如果要确保std::string调用版本,则需要给它一个std::string

Output::Print(std::string("Hello World"));
于 2013-02-08T10:18:22.460 回答
13

不知道为什么没有人发布这个,但您可以添加另一个重载,为您从 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));
    }
};
于 2018-12-05T11:57:28.510 回答
10

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);
}
于 2017-03-16T12:26:34.527 回答
1

从 C++14 开始,我们有了operator""sfromstd::string_literals命名空间,它可以用来告诉编译器绑定到string(或string_view在 C++17 中)重载:

using namespace std::string_literals;
Output::Print("Hello World"s);

印刷:Hello World

于 2021-01-16T17:39:00.573 回答