C++隐式类型转换

C++ implicit typecast

本文关键字:类型转换 C++      更新时间:2023-10-16

我想将许多相似的类相互转换。它们至少有一个共同的抽象祖先,它定义了 2 种基本方法。

我遇到了奇怪的类型转换错误,所以我做了一个简化的例子。在层次结构的顶部:Integer 类。它是一个具有int val()方法的抽象类。其中一个子值只是物理int值的持有者,而另一个引用 2 个整数,val() 是其两个引用的整数的总和。

我写了这段代码,我不明白为什么注释表达式在使用临时变量时无法编译,效果很好。

class Sum;
class Integer {
    public:
        virtual int val(void) const = 0;
        Sum operator+(Integer & other);
};
class Sum : public Integer {
    private:
        Integer &op1, &op2;
    public:
        explicit Sum(Integer &a, Integer &b) : op1(a), op2(b) {};
        int val(void) const {return op1.val() + op2.val();};
};
class Int : public Integer {
    private:
        int v;
    public:
        Int(int value=0) : v(value) {};
        Int(Integer & other) : v(other.val()) {};
        int val() const {return v;};
        Int & operator=(Integer & other){v = other.val(); return *this;};
        Int & operator=(int value){v = value; return *this;};
};
std::ostream & operator<<(std::ostream & out, Integer & i){return out << i.val();}
Sum Integer::operator+(Integer & other){return Sum(*this, other);}
int main(int argc, const char **argv){
    Int a=42, b=57;
//  Int s = a+b; => conversion from ‘Sum’ to non-scalar type ‘Int’ requested
    Sum r = a+b;
    Int s = r;       /* OK */
    cout << a << " + " << b << " = " << s << endl;
    return 0;
}
class Int : public Integer {
    private:
        int v;
    public:
        Int(int value=0) : v(value) {};
        Int(Integer & other) : v(other.val()) {};
        int val() const {return v;};
        Int & operator=(Integer & other){v = other.val(); return *this;};
        Int & operator=(int value){v = value; return *this;};
};

构造函数Int(Integer & other)不会修改其参数,因此可以(应该)将该引用const

Int(Integer const& other) : v(other.val()) {};

这也解决了您的问题:

Sum Integer::operator+(Integer & other);
Int s = a+b;

operator +(可以说应该是一个自由函数而不是成员函数)返回一个 Sum 类型的 prvalue/temporary 。此临时不能绑定到非常量左值引用,因此不能使用构造函数Int(Integer & other)

类似地,对于Int & operator=(Integer & other),常量引用就足够了。

对于接受非常量引用的函数,例如 Int 的构造函数,不能传递临时对象。 对此的一个常见解释是,如果函数采用非常量引用,则允许修改引用,但是对于临时对象,此更改实际上不会发生,因为引用变量在函数调用之外无法访问。

正如 DyP 在注释中建议的那样,将值更改为 const 将提供一个解决方案,或者您可以简单地将其绑定到变量,就像您使用 'Sum r = a+b' 所做的那样。