C++转换运算符与构造函数优先级,编译器不同

Kov*_*vaz 6 c++ gcc casting

我有2个非常简单的类,ClassA和ClassB.我希望能够从ClassB转换为ClassA.使用Sun C++ 5.11,它可以很好地编译并按照我的预期运行,根据这个:转换构造函数与转换运算符:优先级.

当我尝试使用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 );
}
Run Code Online (Sandbox Code Playgroud)

使用Sun C++ 5.11,它可以很好地编译并吐出以下输出:

Creating b:
ClassB int constructor
Casting b to a ClassA:
ClassB operator ClassA()
ClassA int constructor 
Run Code Online (Sandbox Code Playgroud)

使用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
Run Code Online (Sandbox Code Playgroud)

如果我注释掉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
Run Code Online (Sandbox Code Playgroud)

为什么gcc认为这两个转换序列是等价的:

ClassB :: operator ClassA()
ClassB :: operator int() - > ClassA :: ClassA(const int&)

101*_*010 4

如果您的编译器支持 C++11 功能,您可以显式声明转换运算符:

class ClassB
{
    public:
    explicit ClassB( const int& num );

    explicit operator ClassA() const throw();
    explicit operator int() const throw();
    explicit operator float() const throw();

    int getNumber() const;

    private:
    int _number;
}
Run Code Online (Sandbox Code Playgroud)

展示

因此,编译器不会在重载决策中与 static_cast<>由于隐式转换而必须进行选择的不明确调用相混淆。