重载,可变函数和bool类型

Jab*_*cky 8 c++ c++11

以下程序编译好并按预期工作.它的输出是:

1
2

#include <stdio.h>

class Foo
{
public:
  void Bar(const char* b, ...) { printf("1\n"); };
  void Bar(int a, const char* b, ...) { printf("2\n"); };
};

int main()
{
  Foo foo1;
  foo1.Bar("Test", "xx", 1, 2);
  foo1.Bar(1, "xx", "xx", 2, 2);
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我改变int的第二个参数Bar的功能为boolfoo1.Bar(1, "xx", "xx", 2, 2);foo1.Bar(true, "xx", "xx", 2, 2);,那么,下面一行将无法编译,我得到的错误:'Foo::Bar': 2 overloads have similar conversions:

  foo1.Bar("Test", "xx", 1, 2);
Run Code Online (Sandbox Code Playgroud)

整个程序不编译:

#include <stdio.h>

class Foo
{
public:
  void Bar(const char* b, ...) { printf("1\n"); };
  void Bar(bool a, const char* b, ...) { printf("2\n"); };
};

int main()
{
  Foo foo1;
  foo1.Bar("Test", "xx", 1, 2);  // error: 'Foo::Bar': 2 overloads have similar conversions
  foo1.Bar(true, "xx", "xx", 2, 2);
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么第二种情况存在歧义.

编辑

但如果指针隐式转换为bool,为什么后续编译?

#include <stdio.h>

class Foo
{
public:
  void Bar(const char* b) { printf("1\n"); };
  void Bar(bool a) { printf("2\n"); };
};

int main()
{
  Foo foo1;
  foo1.Bar("Test");
  foo1.Bar(true);
}
Run Code Online (Sandbox Code Playgroud)

Don*_*ang 5

这可以:

#include <stdio.h>

class Foo
{
public:
  void Bar(const char* b, ...) { printf("1\n"); };
  void Bar(bool a, ...) { printf("2\n"); };
};

int main()
{
  Foo foo;
  foo.Bar("Test");
}
Run Code Online (Sandbox Code Playgroud)

这不好:

#include <stdio.h>

class Foo
{
public:
  void Bar(const char* b, ...) { printf("1\n"); };
  void Bar(bool a, char another, ...) { printf("2\n"); };
};

int main()
{
  Foo foo;
  foo.Bar("Test", 'c');  // Ambiguous!
}
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,Bar()的第一个版本显然更好.但在第二种情况下,它不再那么清楚了,因为虽然第一个版本与参数1的匹配更好,但第二个版本与参数2的匹配更好.

剩下的问题是:为什么使用'int'代替'bool'可以避免歧义?答案是指针可能隐式转换为bool而不是int.


T.C*_*.C. 5

当您匹配"Test", "xx", 1, 2const char*, ...,第一个参数的转换序列具有完全匹配等级,第二个到第四个参数的转换序列是省略号转换序列.所以(完全匹配,省略号,省略号,省略号).

匹配"Test", "xx", 1, 2bool, const char*, ...,第一个参数的第一个转换序列具有转换等级; 第二个是精确匹配,第三个和第四个是省略号转换序列.换句话说,(转换,精确匹配,省略号,省略号).

完全匹配击败转换; 一切都胜过省略号(见[over.ics.rank]).因此,我们在这里有一个所谓的纵横交错的情况,其中一个函数对于一个参数具有更好的转换序列,而另一个函数具有用于另一个参数的更好的转换序列.由于函数比另一个函数更好的必要(但不充分)条件是没有一个转换序列比其他函数([over.match.best]/1)更差,这两个函数都没有比另一个好.