转换构造函数和运算符都存在且涉及显式性时的行为
Behavior when both conversion constructor and operator are present and explicitness is involved
我有一段代码,其中我有转换构造函数和转换运算符。
#include <iostream>
struct ClassFloat;
struct ClassInt{
int value;
ClassInt(int c) : value(c){std::cout << "From integern";};
ClassInt(ClassFloat x);
//explicit ClassInt(ClassFloat x);
};
struct ClassFloat{
float val;
explicit operator ClassInt() {std::cout << "Conversion operator calledn"; return ClassInt{999};}
//operator ClassInt() { std::cout << "Conversion operator calledn"; return ClassInt{999};}
};
ClassInt::ClassInt(ClassFloat x){
std::cout << "Conversion constructor called!n";
value = (int)x.val;
}
int main(){
ClassFloat floatObj{3.5f};
ClassInt instance1 = floatObj; // (1)
ClassInt instance2 = (ClassInt)floatObj; // (2)
return 1;
}
- 如果两者都是非显式的。我收到一个编译器错误,说第一个表达式不明确。第二个表达式调用构造函数。
- 如果只有运算符是显式的,则两个转换都使用构造函数。
- 如果只有构造函数是显式的,则第二次转换调用构造函数,第一个转换使用运算符。
- 如果两者都是显式的,我只能编译第二个表达式。它使用构造函数。
我不明白为什么在第二个场景中的第二个表达式中不调用转换运算符。
我也期待第四种情况下会出现歧义错误(类似于第一个场景),但选择了构造函数。
我使用 g++ 7.4.0 编译,带有 -pedantic 和 -std=c++17 标志。
首先,c型演员表演static_cast
,然后
(强调我的)
1)如果存在从
expression
到new_type
的隐式转换序列,或者如果直接初始化对象的重载分辨率或来自expression
的new_type
类型的引用将找到至少一个可行的函数,则static_cast<new_type>(expression)
返回虚变量Temp
初始化,就像通过new_type Temp(expression);
一样, 这可能涉及隐式转换、对new_type
构造函数的调用或对用户定义的转换运算符的调用。
所以给定(ClassInt)floatObj;
(初始化好像ClassInt Temp(floatObj);
),转换构造函数总是首选,它将直接用于构造ClassInt
。应用转换运算符需要从floatObj
到ClassInt
的隐式转换(然后在概念中复制初始化临时ClassInt
)。
对于第一种情况,您观察到的结果似乎与上述摘要略有不同,
- 如果两者都是非显式的。我收到一个编译器错误,说它不明确。
只有第一个表达式会导致歧义问题,第二个表达式将使用转换构造函数。
顺便说一句:我尝试使用 gcc 7.3.0,它给出了预期的结果。
为了回答您的问题,
我不明白为什么在第二个场景中的第二个表达式中不调用转换运算符。
因为转换构造函数是第二个表达式(c-ctyle 强制转换)的首选。
我也期待第四种情况下会出现歧义错误(类似于第一个场景),但选择了构造函数。
与上面相同,转换构造函数是第二个表达式的首选;第一个表达式会导致错误,因为转换构造函数和转换运算符都标记为explicit
。
另请注意,第一个表达式需要隐式转换,那么转换构造函数或转换运算符是否标记为explicit
确实很重要。另一方面,第二个表达式是显式转换,它并不关心这一点。
- 构造函数和转换运算符之间的重载解析
- 复制构造函数、赋值运算符C++
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 为用户定义的类正确调用复制构造函数/赋值运算符
- C++矢量复制构造函数和赋值运算符是否也复制保留空间?
- 为什么我的运算符 + 重载尽管是通过引用传递的,但仍调用我的复制构造函数?
- 让某个类的 '=' 运算符在声明时运行构造函数
- C++:使用运算符 = 调用多参数构造函数
- 应用于运算符而不是构造函数的显式关键字
- 运算符+ 的规范实现涉及额外的移动构造函数
- 运算符 new 的执行顺序和构造函数的参数
- 非模板 std::reference_wrapper赋值运算符和模板构造函数
- 如果我也使用复制构造函数并且重载 = 运算符,我是否需要析构函数?
- 复制构造函数和赋值运算符的值类实现
- 在构造函数中使用重载运算符?
- 在C++中,我可以在定义自己的复制构造函数后跳过定义赋值运算符吗?
- 将内置类型变量传递给只有一个类类型参数的"+"运算符函数时自动类型转换的构造函数
- C++ 类的构造函数和函数调用运算符 () 重载之间的歧义
- 删除了所有自动生成的构造函数/运算符的类仍然可以从函数返回吗
- 为简单结构定义哪个复制/移动构造函数/运算符