【问题标题】:Overloading, variadic functions and bool type重载、可变参数函数和布尔类型
【发布时间】:2016-10-05 06:31:12
【问题描述】:

以下程序可以正常编译并按预期工作。它的输出是:

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);
}

现在,如果我将第二个 Bar 函数的 int 参数更改为 bool 并将 foo1.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);

没有编译的整个程序:

#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);
}

我不明白为什么第二种情况有歧义。

编辑

但是如果指针隐式转换为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);
}

【问题讨论】:

  • 这与可变参数函数无关,如果你构建了一个 minimal 测试用例,你就会发现。
  • @LightnessRacesinOrbit 我刚刚编辑了问题并添加了一个最小的测试用例,没有编译的可变参数函数......
  • @robor78 问题相似但不一样。这里我们有const char*,它是一个内置类型,而在另一个问题中有一个string,它是一个用户定义类型
  • …………呸。

标签: c++ c++11


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    这很好:

    #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");
    }
    

    这样不好:

    #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!
    }
    

    在第一种情况下,Bar() 的第一个版本显然更好。但是在第二种情况下,就不是那么清楚了,因为第一个版本对参数 1 的匹配更好,而第二个版本对参数 2 的匹配更好。

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

    【讨论】:

    • 我编辑了这个问题:那么为什么最后一个案例没问题?
    • 您新添加的案例相当于我的回答中的第一个案例:如果您使用“const char*”调用,那么采用“const char*”的 Bar() 版本显然更好;如果你用 'bool' 调用,那么采用 'bool' 的 Bar() 版本显然更好。隐式转换仍然是转换。不需要转换其参数的函数(如果存在)优先。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-10
    相关资源
    最近更新 更多