【发布时间】:2014-07-28 04:41:25
【问题描述】:
我有 2 个非常简单的类,ClassA 和 ClassB。我希望能够从 ClassB 转换为 ClassA。使用 Sun C++ 5.11,它可以很好地编译并完全按照我的预期运行,根据:Conversion constructor vs. conversion operator: precedence。
当我尝试使用 gcc 版本 4.8.2 编译它时,它给出了一个关于对重载函数的模棱两可调用的错误。当强制转换似乎是一种定义明确的行为时,为什么会有不同的行为?
守则:
main.cc
#include <iostream>
class ClassB;
class ClassA
{
public:
ClassA( const int& num )
: _number( num )
{ std::cout << "ClassA int constructor\n"; }
private:
int _number;
};
class ClassB
{
public:
ClassB( const int& num )
: _number( num )
{ std::cout << "ClassB int constructor\n"; }
operator ClassA() const throw()
{
std::cout << "ClassB operator ClassA()\n";
return ClassA( _number );
}
operator int() const throw()
{
std::cout << "ClassB operator int()\n";
return _number;
}
private:
int _number;
};
int main( int argc, const char* argv[] )
{
std::cout << "Creating b:\n";
ClassB b( 5 );
std::cout << "Casting b to a ClassA:\n";
ClassA a = static_cast<ClassA>( b );
}
使用 Sun C++ 5.11,它可以正常编译并输出以下输出:
Creating b:
ClassB int constructor
Casting b to a ClassA:
ClassB operator ClassA()
ClassA int constructor
使用gcc,编译器吐出如下错误:
main.cc: In function 'int main(int, const char**)':
main.cc:43:36: error: call of overloaded 'ClassA(ClassB&)' is ambiguous
ClassA a = static_cast<ClassA>( b );
^
main.cc:43:36: note: candidates are:
main.cc:8:2: note: ClassA::ClassA(const int&)
ClassA( const int& num )
^
main.cc:5:7: note: ClassA::ClassA(const ClassA&)
class ClassA
如果我注释掉 ClassB::operator int() 或 ClassA::ClassA( const int& ),它可以正常编译并给出相同的输出。如果我注释掉 ClassB::operator CLassA(),我会得到以下输出:
Creating b:
ClassB int constructor
Casting b to a ClassA:
ClassB operator int()
ClassA int constructor
为什么gcc认为这两个转换序列是等价的:
ClassB::运算符 ClassA()
ClassB::operator int() -> ClassA::ClassA( const int& )
【问题讨论】:
-
要演示这个问题的代码太多了。
-
一些额外的上下文:在实际出现的代码中,有一个“ClassA”,但有很多不同的“ClassB”需要转换为“ClassA”。提出的一个解决方案是实现一个方法 ClassB::toClassA(),它返回一个与 ClassB::operator ClassA() 相同的 ClassA 对象。虽然这将使这个编译并正常工作,但我想了解导致当前方法不起作用的实际情况。
-
@chris:怎么会这样?为了演示它,我需要两个类,一个具有多个转换运算符,一个具有多个构造函数。我还尝试使实现尽可能与实际类相似,以防我忽略的一些实现细节是问题。
-
您应该将它放在一个文件中,我们可以将其复制粘贴到编辑器中(因为问题不在于多个文件)。与其担心它与你的代码很接近,你应该尽可能地减少它,然后验证它是否仍然存在同样的问题。
-
包含调试输出的代码实际上很有帮助。