C ++类型转换运算符

时间:2019-03-13 16:39:05

标签: c++ types casting

我正在研究运算符重载,其中有些部分难以理解。

请参阅此示例代码。

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运算符?

祝你有美好的一天! :)

2 个答案:

答案 0 :(得分:7)

您忘记了const转换运算符上的double

operator double() const {  // <---------------------------
        cout << "operator double() called" << endl;
        return this->c;
    }
};

在您的示例中,a不是const,因此两次转换是最佳匹配。如果修复,则将获得预期的输出。

Live example

...一些基于意见的PS:

我没有找到有关转换运算符的核心准则,但是如果我必须为转换运算符制定一个准则,那就是:避免使用它们。如果使用它们,请将它们设置为explicit。隐式转换的令人惊讶的影响远远超过了收益。

仅作为示例,考虑std::bitset。它没有提供转换运算符,而是具有to_stringto_ulongto_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;
}