【问题标题】:c++ function overload ambiguousc++ 函数重载不明确
【发布时间】:2012-05-06 13:59:30
【问题描述】:

在 C++ 中

void foo(int i)
{ std::cout<<"int"<<std::endl; }

void foo(float i)
{ std::cout<<"float"<<std::endl; }

void foo(void *i)
{ std::cout<<"void *"<<std::endl; }

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

void main() { foo(0); }

编译时出错。
在 visual-studio 2008 中,错误是 C2668:'function' : ambiguous call to overloaded function

我知道为什么会出现这个问题,并且我知道使用时间类型转换的解决方案。但我认为这不是一个好的解决方案,因为使用这种方式会扼杀函数重载的词汇性。

在我的项目中,我制作了一个词法对象,将自动类型更改为 int、float、std::basic_string 和函数指针。重载所有类型转换运算符和创建者。但是当我输入“NULL”时,会出现错误 C2668。

其实几乎没有问题。唯一严重的问题是使用 FALSE 时。我的项目是核心库,所以我不能指导每个终端客户程序员。

谁知道以更聪明的方式解决这个问题的诀窍或技巧?

【问题讨论】:

  • 这在 gcc 4.5 上编译得很好。
  • 如果这是您的真实代码,请报告编译器错误

标签: c++ operator-overloading overloading lexical


【解决方案1】:

就目前而言,您的代码不应导致错误——没有歧义。当传递0int)时,很明显foo(int)(身份转换)比其他任何一个都更合适(即使 0 也可以隐式转换为所有其他重载的类型)。

我的直接猜测是您正在测试的代码与您发布的代码不太一样。例如,如果您没有让重载采用int,我预计会出现关于模棱两可重载的错误(因为如上所述,存在从0 到类型的隐式转换被所有其他重载占用)。我已经确认 VC++ 2008 按原样接受代码(VC 2010 以及 VC11 和 g++ 4.7.0 的测试版也是如此)。

顺便说一句,我注意到main 应该真正返回int(尽管它几乎肯定与手头的问题无关)。

【讨论】:

  • 你是对的。为了避免问题变得过于复杂,我只是简化了它。我使用 vs2008 并且我重载了 int、unsigned int、long、unsigned long。因为每个程序员都使用 STL,它有时会返回 size_t 或其他程序员使用 DWORD。所以我现在只有一个 int 系列的重载 int,忽略类型转换的编译器警告。
【解决方案2】:

C++11 通过引入一个新的关键字来作为一个可区分的空指针常量来纠正这个问题:nullptr。它是 nullptr_t 类型,它可以隐式转换并且与任何指针类型或指向成员的指针类型相当。它不能隐式转换或与整数类型相比较,除了 bool。

【讨论】:

    【解决方案3】:

    也许您可以将FALSE 定义为((bool)0) 而不仅仅是0(为什么不使用false 代替?!)。

    另外,如果您考虑一下,拥有f(int *)f(char *) 并调用f(NULL) 模棱两可,所以无论如何你都需要一个演员表!除非您告诉编译器,否则编译器不会神奇地知道您的意图。因此,如果某些内容本质上是模棱两可的,则只需通过强制转换使其明确即可。

    【讨论】:

    • 在 C++ 中,#define NULL ((void *)0) 是有害的。这意味着您必须在每次使用 NULL 时添加演员表。一般来说,覆盖标准库定义的东西似乎是一个非常糟糕的主意。
    • 好的,我用这种方式测试,但我遇到了同样的问题。十分感谢。我只是在这个模棱两可的情况下使用'int'。 void*(函数指针)是其他的 setter/getter 模板函数。我认为模棱两可的问题是不可避免的。
    • 定义标准库定义的任何标记都是未定义的行为(即使您没有包含该标头)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    • 2011-06-08
    • 2012-12-19
    • 2021-11-02
    • 1970-01-01
    • 2017-05-11
    • 2014-11-13
    相关资源
    最近更新 更多