简体   繁体   English

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

[英]C++ : user defined Explicit type conversion function error

Here is how the code looks:下面是代码的样子:

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;
}

I'm using ms vs compiler here and getting c2440 (type cast error).我在这里使用 ms vs 编译器并获得 c2440(类型转换错误)。 To my understanding, I'm not doing anything wrong syntax-wise.据我了解,我在语法上没有做任何错误的事情。 The problem here is that it works fine if I remove the implicit conversion: operator int() and its respective function out of the code.这里的问题是,如果我从代码中删除隐式转换: operator int()及其各自的函数,它就可以正常工作。 ie: IE:

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;
}

this will produce the following output (as expected):这将产生以下输出(如预期):

val.x: 9

Edit: explicit keyword was missing in the second example.编辑:第二个示例中缺少显式关键字。 The output is the same输出是一样的

There is an ambiguity between the way an object of the type dummy can be created.创建dummy类型的对象的方式存在歧义。

The first one is when the operator dummy is called creating a temporary object of the type dummy and then the copy constructor is called due to the explicit cast conversion.第一个是当operator dummy被调用以创建一个dummy类型的临时对象,然后由于显式强制转换而调用复制构造函数。

The second one is when the object of the type myClass is converted to the type int due to the operator int and then the conversion constructor of the class myClass is called to create an object of the type dummy .第二个是当myClass类型的对象由于operator int被转换为int类型,然后调用myClass类的转换构造函数来创建一个dummy类型的对象。

Here is a demonstrative program that shows the two ways of creating an object of a class using the explicit casting.这是一个演示程序,它显示了使用显式转换创建类对象的两种方法。

#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;
}

The program output is程序输出是

A( 1 )

A( const A & )

A( 2 )

Relative to your program then in your program there is one additional step before using these ways: either an object of the type myClass will be preliminary converted to the type dummy or to the type int .相对于您的程序,在您的程序中,在使用这些方法之前还有一个额外的步骤: myClass类型的对象将被初步转换为dummy类型或int类型。

Compiling your original code with gcc-9 on ubuntu 18.04 I get this:在 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&&)’

What is happening is the compiler cannot tell if you want to create a new 'dummy' class out of the int conversion of 'myClass' or a new 'dummy' out of the implicitly generated copy operator of 'dummy'.发生的事情是编译器无法判断您是要从“myClass”的 int 转换中创建一个新的“dummy”类,还是从“dummy”的隐式生成的复制运算符中创建一个新的“dummy”。

This causes a loop where 'myClass' can be converted to both int and dummy which means that compiler gets stuck trying to convert 'myClass' since it doesnt know what you actually want to do - convert to 'dummy', convert to 'dummy' then copy it, or make a new 'dummy' by converting 'myClass' to int这会导致一个循环,其中 'myClass' 可以转换为intdummy ,这意味着编译器在尝试转换 'myClass' 时卡住了,因为它不知道你真正想要做什么 - 转换为 'dummy',转换为 'dummy'然后复制它,或者通过将 'myClass' 转换为int来创建一个新的 'dummy'

The solution to this is to make your conversion operator to int explicit this prevents implicit conversion by the compiler and allows this to work (at least on gcc-9).解决这个问题的方法是让你的转换运算符explicit式地转换为 int,这可以防止编译器进行隐式转换并允许它工作(至少在 gcc-9 上)。

This is an updated copy of your code which will work:这是您的代码的更新副本,它将起作用:

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;
}

This compiles with gcc-9 and clang++-9这用 gcc-9 和 clang++-9 编译

As a side note please please please never use C style casts in C++, they are error prone and a pain in the ass to debug作为旁注,请不要在 C++ 中使用 C 风格的强制转换,它们容易出错并且调试起来很麻烦

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM