//############################################################################
/* 隐式类型转换
*
* 类型转换可分为:
* 隐式 显式
* 标准类型转换 A B
* 用户定义类型转换 C D
* (casting)
*
*
* A: 隐式标准类型转换
*/
char c = 'A';
int i = c; // 整型提升
char* pc = 0; // int -> Null pointer
void f(int i);
f(c);
dog* pd = new yellowdog(); // 指针类型转换
/*
* C: 隐式用户定义类型转换
*
* 在类内定义
*
* 转换 1: 将其他类型对象转成当前类型的对象
* - 具有可以接收一个参数的构造函数
* 转换 2: 将当前类对象转换成其他类型
* - 使用类型转换函数
*/
class dog {
public:
dog(string name) {m_name = name; } // NO explicit,单个参数的构造函数,如果没有显式地explicit,它同时也是类型转换函数
// 如果不想隐式地定义类型转换,加上explicit
string getName() {return m_name;}
private:
string m_name;
};
void main ()
{
string dogname = "Bob";
dog dog1 = dogname;
printf("My name is %s.\n", dog1.getName());
}
OUTPUT:
My name is Bob
/* 原则: 使接口易于正确使用,不易错误使用
* 理想情况,无法编译通过
*
* 一般指导原则:
* 1. 避免定义看起来不期望的转换
* 2. 避免双向隐式转换,会出现二义性
*/
//转换 2:
//operator string () const { return m_name; }
// string str = dog1;
//
/* 隐式类型转换在处理数值类型的类时很有用
* 比如分数类
*/
class Rational {
public:
Rational(int numerator = 0, int dennominator = 1):
num(numerator),den(denominator) {}
int num; // Demo only, public data members are not recommended
int den;
const Rational operator*(const Rational& rhs) {
return Rational(num*rhs.num, den*rhs.den);
}
};
int main ()
{
Rational r1 = 23;
Rational r2 = r1 * 2;
}
// Rational r3 = 3 * r1; //如果要想使用需要定义非成员函数版本运算符函数
const Rational operator*( const Rational& lhs, const Rational& rhs) {
return Rational(lhs.num*rhs.num, lhs.den*rhs.den);
}
// 如果同时定义了类对象到外部类型的转换:
operator int () const { return num/den; }
// 会出现二义性