【问题标题】:c++ conversion operator overloading, enums, ints and charsc++ 转换运算符重载、枚举、整数和字符
【发布时间】:2011-11-18 00:56:22
【问题描述】:

当我尝试编译(使用 gcc 4.3.4)这段代码 sn-p:

enum SimpleEnum {
    ONEVALUE
};

void myFunc(int a) {
}

void myFunc(char ch) {
}

struct MyClass {
    operator int() const { return 0; };
    operator SimpleEnum() const { return ONEVALUE; };
};

int main(int argc, char* argv[]) {
    myFunc(MyClass());
}

我收到此错误:

test.cc: In function "int main(int, char**)":
test.cc:17: error: call of overloaded "myFunc(MyClass)" is ambiguous
test.cc:5: note: candidates are: void myFunc(int)
test.cc:8: note:                 void myFunc(char)

我想我(几乎)理解问题所在,即(简化了很多)即使我谈到“char”和“enum”,它们都是整数,然后重载是模棱两可的。

无论如何,我不太明白的是,如果我删除 myFunc OR 的转换运算符之一的第二个重载 MyClass em>,我没有编译错误。

由于这个问题我要更改很多旧代码(我正在将代码从旧版本的 HP-UX aCC 移植到 Linux 下的 g++ 4.3.4),我想更好地理解为了选择最好的方式修改代码。

提前感谢您的帮助。

【问题讨论】:

  • 如果您删除转换为int,它对您有用吗?还是像其他人建议的那样从枚举到 int/char 的转换仍然模棱两可?
  • @K-ballo:如果我删除两个转换之一,它会起作用。如果我删除“void myFunc(char ch)”,它会起作用。如果我删除“void myFunc(int a)”,我会得到(几乎)同样的错误。
  • 我坚持认为,上面的示例没有编译,而没有“void myFunc(char ch)”编译的示例,从常识的角度来看显然是错误的,当然,违反直觉。无论如何,从您的回答中,我知道这是(丑陋的)标准,我会尊重它(也因为我别无选择)。仅供参考,我决定将显式强制转换为 int 到我的生产代码中。感谢任何回答并因此帮助我更好地理解整个事情的人。

标签: c++ enums operators overloading ambiguous


【解决方案1】:

MyClass 的转换是不明确的,因为有一个到int 的转换和一个到枚举的转换,它本身可以隐式转换为int,两者都是同样好的转换。不过,您可以通过指定所需的转换来明确调用:

myfunc(int(MyClass()));

或者,您可能想重新考虑为什么您有一个函数具有单独的 intchar 重载,也许也可以重新设计。

【讨论】:

  • 歧义不在enumintchar之间,它实际上在enum之间,可转换为int,用户定义转换为int。调用 yo myFunc( ONEVALUE ) 应该没问题,并且会选择 int 重载。
  • @K-Ballo:你说得对,我搞砸了。让我修复它。谢谢!
  • 这两个转换运算符可能是“冲突的”这一事实对我来说很清楚,而且我可以通过明确指定要使用的转换来解决这个问题,这在我在这里发布之前得到了验证。无论如何,最让我不安的是,如果我删除 myFunc 的“char”重载,一切正常。但是 MyClass 的两次转换仍然存在,为什么我不再收到错误?我希望了解这一事实可以帮助我找到合适的解决方案(显式转换会导致代码的重大返工,因此,我试图避免它)。
  • @port: 如果myfunc只有一个版本,那么转换成int比较好,因为它需要no隐式转换,所以没有模棱两可。
【解决方案2】:

enums are types in C++,不像 C。

enum -> charenum -> int 都有隐式转换。编译器只是不知道该选择哪一个。


编辑:尝试不同的测试后:

  • 当自定义转换的定义 MyClass -> int 被移除时,代码编译。

  • 这里有枚举到int 的隐式转换,因此它是编译器所青睐的,而不是charTest here

  • 删除 void myFunc(int) 的定义时,编译失败。

  • 编译器尝试从MyClass 转换为char,并发现在没有用户定义的转换运算符char() 的情况下,可以使用用户定义的int()SimpleEnum()Test here

  • 当您为 MyClass 添加 char() 转换运算符时,编译失败并出现与未添加时相同的错误。

  • Test here.

所以我在这里得出的结论是,在您最初发布的代码中,编译器必须决定应该调用myFunc 的两个重载版本中的哪一个。 由于两种转换都是可能的:

  1. MyClassint 通过用户定义的转换运算符。
  2. MyClassint 通过用户定义的转换(MyClassSimpleEnum)+ 隐式转换(SimpleEnumchar

编译器不知道使用哪一个。

【讨论】:

  • 歧义不在enumintchar之间,它实际上在enum之间,可转换为int,用户定义转换为int。调用 yo myFunc( ONEVALUE ) 应该没问题,并且会选择 int 重载。
  • 那为什么编译器会产生误导性的错误描述?
  • @K-ballo:看起来它是两者的结合,看看这个:ideone.com/75Huq
  • 确实,如果唯一的重载是 int ,那么用户定义的到 int 的转换是“更短”的路径,因此被选中。我仍然认为这段代码不应该导致编译器错误,因为在每种情况下都应该选择用户定义的到 int 的转换......我希望标准大师告诉我们代码是否合法。
  • @K-ballo:实际上我希望选择更短的路径(旧的 aCC 编译器会发生这种情况,因为它与当前的 C++ 标准不是最新的)
【解决方案3】:

我本来希望调用 int 重载。尝试了一些编译器并得到了不同的结果。如果要删除任何内容,请将用户转换运算符删除为int,因为枚举具有到整数的标准转换。

【讨论】:

  • 不幸的是,实际情况比我发布的示例要复杂一些:我有可以转换为 int 以便存储到 DB 并且可以转换为其他枚举的伪枚举类它们是 CORBA 枚举,以便与其他进程通信。我真的无法删除任何转换(或者我可以,然后我必须手动修复数千行代码,在数十万行代码中搜索它们)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 2013-08-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多