【问题标题】:C++ function overload priority [duplicate]C ++函数重载优先级[重复]
【发布时间】:2015-06-23 07:53:31
【问题描述】:

为什么代码会给出输出:bool? 有什么办法可以让const char* 匹配string 版本?

#include <string>
#include <iostream>

void func(bool)
{
    std::cout << "bool" << std::endl;
}

void func(const std::string&)
{
    std::cout << "string" << std::endl;
}

int main(int argc, char* argv[])
{
    func("hello");
}

【问题讨论】:

  • func(std::string("hello"));
  • 没有明确构造std::string的任何替代方案?我希望编译器给出一个模棱两可的警告,而不是匹配 bool 版本。
  • 也许有一个编译器选项,但它会依赖于编译器 try -Wall on gcc
  • @prmottajr 我在 clang 上尝试了-Wall,但没有显示警告。
  • 您不会收到模棱两可的警告,因为调用并不模棱两可。

标签: c++ overloading


【解决方案1】:

发生这种情况是因为编译器更喜欢内置转换而不是用户定义的转换。从指针到bool 的转换是内置的,因此选择重载而不是构造std::string

您可以添加一个采用const char* 的重载并将其转发到std::string 版本:

void func(const char* arg)
{
    func(std::string{arg});
}

【讨论】:

【解决方案2】:

回答原因:

函数匹配是编译器在重载集中选择调用哪个函数的过程。 在这里,有两个可行的候选者(您定义的两个函数)。要选择一个,编译器会对它们所暗示的转换进行排名。

第一个候选void func(bool) 表示数组到指针的转换,然后是布尔转换(从const char[6]const char*bool) 第二个候选意味着用户定义的转换(调用std::string ctor 采用const char*

第二次转换的排名较低,因此选择第一个候选者作为最佳匹配。

【讨论】:

  • 谢谢安吉!所以 C++ Primer 的术语很草率... (6.6.1)
【解决方案3】:

根据标准N4431§13.3.3.2/2 排名隐式转换序列 [over.ics.rank] (强调我的)

比较隐式转换序列的基本形式时(如 在 13.3.3.1) (2.1) 中定义 — 标准转换序列 (13.3.3.1.1) 是比用户定义的更好的转换序列 转换序列或省略号转换序列,以及 (2.2) — a 用户定义的转换序列(13.3.3.1.2)是更好的转换 序列比省略号转换序列(13.3.3.1.3)。

因此,因为char const *bool 是标准的隐式转换,而与std::string 的隐式转换相比,std::string 是用户定义的转换是更好的转换,并且在重载解决方案中是首选。

为了强制重载解析选择std::string版本:

func(std::string("hello"));

【讨论】:

  • 这看起来是唯一一个直接的答案,它解释了语言是如何工作的,而不把任何责任归咎于“编译器”。
  • @KerrekSB 语言实际上不是由符合标准的编译器定义的吗?
  • @Angew:这是一种非常变态的看待世界的方式,但我想你可以这样看......
  • @KerrekSB 我实际上并没有那样看世界(尽管有 1.1/1 和 1.4/2)。只是我没有看到说“语言规定这个”和“编译器这样做”之间有什么区别。只要编译器遵循标准,我认为这两个是等价的。
  • @Angew:即使您从未编译过代码,代码也是有意义的。不用编译代码就可以谈f(x)这个表达式,重载决议还是有关系的。代码和逻辑比编译行为更基础。用关于编译的辅助思考来污染对代码的讨论似乎是毫无意义的噪音和分心。为什么不讨论一下用粉色 Comic Sans 打印的代码会是什么样子?
猜你喜欢
  • 1970-01-01
  • 2013-03-16
  • 2017-05-21
  • 2012-12-03
  • 2010-11-22
  • 2017-07-27
  • 1970-01-01
  • 2015-01-04
  • 1970-01-01
相关资源
最近更新 更多