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

C++ : user defined Explicit type conversion function error

本文关键字:类型转换 函数 错误 用户 定义 C++      更新时间:2023-10-16

以下是代码的外观:

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

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

在 ubuntu 9 上使用 gcc-18.04 编译您的原始代码 我得到这个:

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"复制运算符中创建一个新的"虚拟"类。

这会导致一个循环,其中"myClass"可以转换为intdummy这意味着编译器在尝试转换"myClass"时陷入困境,因为它不知道您实际上想要做什么 - 转换为"虚拟",转换为"虚拟"然后复制它,或者通过将"myClass"转换为int来制作新的"虚拟"

解决方案是将转换运算符设置为intexplicit这样可以防止编译器进行隐式转换并允许其工作(至少在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 样式的转换,它们容易出错并且调试起来很痛苦

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

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

第二个是当类型myClass的对象由于operator int而转换为类型int,然后调用类myClass的转换构造函数来创建类型为dummy的对象。

下面是一个演示程序,它显示了使用显式强制转换创建类对象的两种方法。

#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类型。