[c++11]用户定义的类型转换

参考:User-Defined Type Conversions (C++)

用户定义的类型转换(user-defined type conversation)可作用于用户定义类型之间,或者用户定义类型和基本类型之间

转换使用

转换过程可通过显式(使用转换运算符)或者隐式完成。隐式转换场景如下:

  1. 输入函数的参数值不匹配参数类型
  2. 函数返回值不符合函数返回值类型
  3. 初始化表达式不符合对象类型
  4. 控制条件语句、循环构造或开关的表达式没有控制它所需的结果类型
  5. 提供给运算符的操作数与匹配的操作数参数的类型不同。对于内置运算符,两个操作数必须具有相同的类型,并且转换为可以表示这两个操作数的公共类型。对于用户定义的运算符,每个操作数必须与匹配的操作数参数具有相同的类型

首先进行标准转换,如果不行再选择合适的用户定义的类型转换

转换构造器

声明转换构造器:

  1. 转换的目标类型是正在构造的用户定义类型
  2. 转换构造函数通常只接受一个源类型的参数。但是,如果每个附加参数都有默认值,则转换构造函数可以指定附加参数。源类型仍然是第一个参数的类型
  3. 转换构造函数与所有构造函数一样,不指定返回类型。在声明中指定返回类型是错误的
  4. 转换构造函数可以使用关键字explicit标识
class Money {
public:
    Money() : amount{0.0} {};

    Money(double _amount) : amount{_amount} {};

    double amount;
};

void display_balance(const Money balance) {
    std::cout << "The balance is: " << balance.amount << std::endl;
}

int main(int argc, char *argv[]) {
    Money payable{79.99};

    display_balance(payable);
    display_balance(49.95);
    display_balance(9.99f);

    return 0;
}

声明为explicit的转换构造器,必须通过显式方式调用

class Money {
public:
    Money() : amount{0.0} {};

    explicit Money(double _amount) : amount{_amount} {};

    double amount;
};

void display_balance(const Money balance) {
    std::cout << "The balance is: " << balance.amount << std::endl;
}

int main(int argc, char *argv[]) {
    Money payable{79.99};        // Legal: direct initialization is explicit.

    display_balance(payable);      // Legal: no conversion required
    display_balance(49.95);        // Error: no suitable conversion exists to convert from double to Money.
    display_balance((Money) 9.99f); // Legal: explicit cast to Money

    return 0;
}

转换函数

转换函数定义从用户定义类型到其他类型的转换

  1. 转换的目标类型必须在声明转换函数之前声明。类、结构、枚举和typedef不能在转换函数的声明中声明
  2. 转换函数不带参数。在声明中指定任何参数都是错误的
  3. 转换函数的返回类型由转换函数的名称指定,该名称也是转换的目标类型的名称。在声明中指定返回类型是错误的
  4. 转换函数可以声明为virtual
  5. 转换函数可以声明为explicit
class Money {
public:
    Money() : amount{0.0} {};

    Money(double _amount) : amount{_amount} {};

    operator double() const { return amount; }

private:
    double amount;
};

void display_balance(const Money balance) {
    std::cout << "The balance is: " << balance << std::endl;
}

同样的,声明为explicit的转换函数必须显式使用

...
    explicit operator double() const { return amount; }
...

void display_balance(const Money balance) {
    std::cout << "The balance is: " << static_cast<double>(balance) << std::endl;
}