玩命加载中 . . .

14.9-重载类型转换运算符


14.9 重载类型转换运算符

类型转换运算符是特殊的成员函数,它负责将一个类类型的值转换成其他类型
一般形式为:

operator type() const;

定义一个比较简单的类,令其表示0到255之间的一个整数

class SmallInt {
public:
    SmallInt(int i=0) : val(i) {
        if (i < 0 || i > 255) 
            throw std::out_of_range("Bad SmallInt value");
    }
    operator int() const { return val; }
private:
    std::size_t val;
};

SmallInt si;
si = 4; // 首先将4隐式地转换成SmallInt,然后调用SmallInt::operator=
si + 3; // 首先将si隐式地转换成int,然后执行整数的加法

/* 可以进行多次转换 */
// 内置类型转换将double实参转换成int
SmallInt si = 3.14; // 调用SmallInt(int)构造函数
// SmallInt类型转换运算符将si转换成int
si + 3.14;  // 内置类型转换将所得的int继续转换成double

类型转换运算符是隐式执行的,不能传递实参

class SmallInt {
public:
    int operator int() const;   // error,不能指定返回类型
    operator int(int=0) const;  // error,不能有参数
    operator int*() const { return 42; }    // error,42不是指针
};

类型转换运算符可能产生意外结果

// 当stream含有向bool的类型转换时
int i = 42;
cin << i;   // cin转为bool值左移42位

为了防止上面的异常,C++11引入了显示的类型转换运算符

class SmallInt {
public:
    // 编译器不会自动执行这一类型转换
    explicit operator int() const { return val; }
};

SmallInt si = 3;    // 正确,SmallInt的构造函数不是显式的
si + 3; // error,此处需要隐式的类型转换,但运算符是显式的
static_cast<int>(si) + 3;   // 正确,显式地请求类型转换

如果表达式被用作条件,编译器会隐式地执行需要显式的类型转换

  • ifwhiledo语句的条件部分
  • for语句头的条件表达式
  • !||&&的运算对象
  • ?:的条件表达式

避免有二义性的类型转换

// 最好不要在两个类之间构建相同的类型转换
struct B;
struct A {
    A() = default;
    A(const B&);    // 把B转换成A
};
struct B {
    operator A() const; // 也是把B转换成A
};

A f(const A&);  // f函数需要一个A对象

B b;
A a = f(b); //二义性错误,含义是f(B::operator A()),还是f(A::A(const B&))?
A a1 = f(b.operatorA());    // 正确
A a2 = f(A(b));     // 正确

函数匹配与重载运算符

class SmallInt {
friend SmallInt operator+(const SmallInt&, const SmallInt&);
public:
    SmallInt(int = 0);  // 转换源为int的类型转换
    operator int() const { return val; }    // 转换目标为int的类型转换
private:
    std::size_t val;
};

SmallInt s1, s2;
SmallInt s3 = s1 + s2;  // 使用重载的operator+
int i = s3 + 0;    // 二义性错误,int可以转为SmallInt,SmallInt也可以转为int

文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录