我正在研究运算符重载,其中有些部分难以理解。
请参阅此示例代码。
class A {
private:
char a;
int b;
double c;
public:
A(char _a = 'a', int _b = 99, double _c = 1.618) :a(_a), b(_b), c(_c){
}
public:
operator char() const {
cout << "operator char() called" << endl;
return this->a;
}
operator int() const {
cout << "operator int() called" << endl;
return this->b;
}
operator double() {
cout << "operator double() called" << endl;
return this->c;
}
};
int main(void) {
A a;
char b = a;
int c = a;
double d = a;
printf("%c\n", b);
printf("%d\n", c);
printf("%f\n", d);
return 0;
}
我编写了这段代码来测试类型转换运算符,并期望为每种数据类型调用适当的函数。
但是结果是..
operator double() called
operator double() called
operator double() called
<-- strange character is gone on board!
1
1.618000
我不明白为什么结果不如下。
operator char() called
operator int() called
operator double() called
a
99
1.618
为什么在转换为char和int时会调用double运算符?
祝你有美好的一天! :)
答案 0 :(得分:7)
您忘记了const
转换运算符上的double
:
operator double() const { // <---------------------------
cout << "operator double() called" << endl;
return this->c;
}
};
在您的示例中,a
不是const
,因此两次转换是最佳匹配。如果修复,则将获得预期的输出。
...一些基于意见的PS:
我没有找到有关转换运算符的核心准则,但是如果我必须为转换运算符制定一个准则,那就是:避免使用它们。如果使用它们,请将它们设置为explicit
。隐式转换的令人惊讶的影响远远超过了收益。
仅作为示例,考虑std::bitset
。它没有提供转换运算符,而是具有to_string
,to_ulong
和to_ullong
。最好让您的代码明确。 A a; double d = a;
有点神秘。我必须查看类定义才能真正了解发生了什么。另一方面,A a; double d = a.as_double();
可以做完全相同的事情,但是更具表现力。
答案 1 :(得分:1)
是的,问题是,您使除double运算符之外的所有运算符均为const。我仍然有些惊讶,因为此const只是意味着操作员调用不会修改类成员。似乎所有3都只调用了double运算符。我将所有3个op的make const都可以正常工作。
如果有人解释为什么会发生这种情况,我也想知道。 干杯。
operator char() const { // here is const
cout << "operator char() called" << endl;
return this->a;
}
operator int() const { // here is const
cout << "operator int() called" << endl;
return this->b;
}
operator double() { // here is no const
cout << "operator double() called" << endl;
return this->c;
}