c++ 转换运算符重载、枚举、整数和字符
Posted
技术标签:
【中文标题】c++ 转换运算符重载、枚举、整数和字符【英文标题】:c++ conversion operator overloading, enums, ints and chars 【发布时间】: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 到我的生产代码中。感谢任何回答并因此帮助我更好地理解整个事情的人。 【参考方案1】:从MyClass
的转换是不明确的,因为有一个到int
的转换和一个到枚举的转换,它本身可以隐式转换为int
,两者都是同样好的转换。不过,您可以通过指定所需的转换来明确调用:
myfunc(int(MyClass()));
或者,您可能想重新考虑为什么您有一个函数具有单独的 int
和 char
重载,也许也可以重新设计。
【讨论】:
歧义不在enum
和int
或char
之间,它实际上在enum
之间,可转换为int
,用户定义转换为int
。调用 yo myFunc( ONEVALUE )
应该没问题,并且会选择 int 重载。
@K-Ballo:你说得对,我搞砸了。让我修复它。谢谢!
这两个转换运算符可能是“冲突的”这一事实对我来说很清楚,而且我可以通过明确指定要使用的转换来解决这个问题,这在我在这里发布之前得到了验证。无论如何,最让我不安的是,如果我删除 myFunc 的“char”重载,一切正常。但是 MyClass 的两次转换仍然存在,为什么我不再收到错误?我希望了解这一事实可以帮助我找到合适的解决方案(显式转换会导致代码的重大返工,因此,我试图避免它)。
@port: 如果myfunc
只有一个版本,那么转换成int
比较好,因为它需要no隐式转换,所以没有模棱两可。【参考方案2】:
enum
s are types in C++,不像 C。
enum
-> char
和 enum
-> int
都有隐式转换。编译器只是不知道该选择哪一个。
编辑:尝试不同的测试后:
当自定义转换的定义MyClass
-> int
被移除时,代码编译。
这里有枚举到int
的隐式转换,因此它是编译器所青睐的,而不是char
。 Test here。删除 void myFunc(int)
的定义时,编译失败。
编译器尝试从MyClass
转换为char
,并发现在没有用户定义的转换运算符char()
的情况下,可以使用用户定义的int()
和SimpleEnum()
。 Test here。当您为 MyClass
添加 char()
转换运算符时,编译失败并出现与未添加时相同的错误。
Test here.
所以我在这里得出的结论是,在您最初发布的代码中,编译器必须决定应该调用myFunc
的两个重载版本中的哪一个。
由于两种转换都是可能的:
MyClass
到 int
通过用户定义的转换运算符。
MyClass
到 int
通过用户定义的转换(MyClass
到 SimpleEnum
)+ 隐式转换(SimpleEnum
到 char
)
编译器不知道使用哪一个。
【讨论】:
歧义不在enum
和int
或char
之间,它实际上在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 枚举,以便与其他进程通信。我真的无法删除任何转换(或者我可以,然后我必须手动修复数千行代码,在数十万行代码中搜索它们)。以上是关于c++ 转换运算符重载、枚举、整数和字符的主要内容,如果未能解决你的问题,请参考以下文章