C++:用户定义的显式类型转换函数错误

C++ : user defined Explicit type conversion function error

代码如下所示:

using namespace std;
class dummy{
public:
    int x;
    explicit dummy(int x = 0) : x{ this->x = x } {}; //explicit has no effect here
};

class myClass {
public:
    operator int(); //<---problematic conversion
    explicit operator dummy();

};

myClass::operator int() {
    return 10;
}

myClass::operator dummy(){
    return dummy(9);
}

int main() {
    myClass mc1; 
    dummy val = (dummy)mc1;
    cout << "mc1 int cast: " << mc1 << endl; 
    cout << "val.x: :" << val.x << endl;
    std::cin.get();
    return 0;
}

我在这里使用 ms vs 编译器并得到 c2440(类型转换错误)。据我了解,我在语法方面没有做错任何事情。这里的问题是,如果我从代码中删除隐式转换:operator int() 及其各自的函数,它就可以正常工作。 即:

using namespace std;
class dummy{
public:
    int x;
    explicit dummy(int x = 0) : x{ this->x = x } {}; //explicit has no effect here
};

class myClass {
public:
    //operator int();
    explicit operator dummy();

};
/*
myClass::operator int() {
    return 10;
}*/

myClass::operator dummy(){
    return dummy(9);
}

int main() {
    myClass mc1; 
    dummy val = (dummy)mc1;
    //cout << "mc1 int cast: " << mc1 << endl; 
    cout << "val.x: " << val.x << endl;
    std::cin.get();
    return 0;
}

这将产生以下输出(如预期的那样):

val.x: 9

编辑:第二个示例中缺少显式关键字。输出相同

类型 dummy 对象的方式之间存在歧义 已创建。

第一个是调用 operator dummy 创建类型 dummy 的临时对象,然后由于显式转换而调用复制构造函数。

第二种是myClass类型的对象由于operator int转换为int类型,然后是class的转换构造函数调用 myClass 以创建 dummy.

类型的对象

这是一个演示程序,展示了使用显式转换创建 class 对象的两种方法。

#include <iostream>

struct A
{
    explicit A( int x = 0 ) : x( x ) { std::cout << "A( " << x << " )\n"; }
    A( const A & ) { std::cout << "A( const A & )\n"; }
    int x;
};

int main() 
{
    A a( 1 );

    std::cout << '\n';

    ( A )a;

    std::cout << '\n';

    ( A )2;


    return 0;
}

程序输出为

A( 1 )

A( const A & )

A( 2 )

相对于你的程序,那么在你的程序中,在使用这些方法之前还有一个额外的步骤:类型 myClass 的对象将被初步转换为类型 dummy 或类型int.

在 ubuntu 18.04 上使用 gcc-9 编译您的原始代码我明白了:

test.cpp:27:24: error: call of overloaded ‘dummy(myClass&)’ is ambiguous
   27 |     dummy val = (dummy)mc1;
      |                        ^~~
test.cpp:7:14: note: candidate: ‘dummy::dummy(int)’
    7 |     explicit dummy(int x = 0) : x{ this->x = x } {}; //explicit has no effect here
      |              ^~~~~
test.cpp:4:7: note: candidate: ‘constexpr dummy::dummy(const dummy&)’
    4 | class dummy{
      |       ^~~~~
test.cpp:4:7: note: candidate: ‘constexpr dummy::dummy(dummy&&)’

发生的事情是编译器无法判断你是想从 'myClass' 的 int 转换中创建一个新的 'dummy' class 还是一个新的 'dummy' 'dummy'.

的隐式生成的复制运算符

这会导致一个循环,其中 'myClass' 可以转换为 intdummy 这意味着编译器在尝试转换 'myClass' 时卡住了,因为它不知道是什么你真的想做 - 转换为 'dummy',转换为 'dummy' 然后复制它,或者通过将 'myClass' 转换为 int[=16 来制作一个新的 'dummy' =]

解决这个问题的方法是让你的转换运算符成为 int explicit 这可以防止编译器进行隐式转换并允许它工作(至少在 gcc-9 上)。

这是您的代码的更新副本,可以使用:

using namespace std;
class dummy{
public:
    int x;
    explicit dummy(int x=0) : x(x) {}


};

class myClass {
public:
    explicit operator int(); // < Set to explicit
    explicit operator dummy();

};

myClass::operator int() {
    return 10;
}

myClass::operator dummy(){
    return dummy(9);
}

int main() {
    myClass mc1; 
    dummy val = static_cast<dummy>(mc1);
    cout << "mc1 int cast: " << static_cast<int>(mc1) << endl; 
    cout << "val.x: :" << val.x << endl;
    std::cin.get();
    return 0;
}

这是用 gcc-9 和 clang++-9 编译的

作为旁注,请永远不要在 C++ 中使用 C 风格的转换,它们容易出错并且调试起来很麻烦