参考自《C++ Primer Plus 6th Edition》
类的自动转换:
说明: C++允许程序员指定类之间进行转换的方式(含基本类型)
站在类的角度看问题,姑且分为“当前类” 和 “其他类”
假设: 当前类是程序员定义的,其他类既可以是程序员定义的,也可以是C++内置的基本类型
方式: 通过定义 “转化函数”
1. 其他类转换为当前类
转化函数:
本质: 允许只传入一个实参的构造函数
包括:
1. 只接受一个参数的构造函数
2. 具有多个形参,但是在类的声明中,存在一个参数没有默认值,但是其他行参都有默认
值的构造函数
那么,这里的 “其他类” 指的就是那个在类声明中没有设置默认值的类型,或者能够与这个类型自动转换的类型
有了转换函数之后呢,我们可以通过自动地将这个 “其他类” 的对象转换为 “当前类” 的对象
举一个例子,实现了内置类型 int (“其他类”) 到Student类 (“当前类”) 的转换
#include <iostream> using namespace std; class Student { private: int id; public: Student() { } Student(int ID) { id = ID; } }; int main() { Student a = Student(1); //explicit Student b(2); //explicit Student c = 3; //implicit return 0; }
再举一个例子 (double 和 int 类型是可以互相自动转换)
#include <iostream> #include <string> using namespace std; class Student { private: int id; public: Student() { } Student(int ID , string name="") { id = ID; } }; int main() { Student a = Student(1); //explicit Student b(2.5); //explicit Student c = 3.7; //implicit return 0; }
2. 当前类转化为其他类
“当前类” 转化为 “其他类” 就稍微麻烦点。因为,它的 “转换函数” 不是构造函数--需要额外定义
形式: operator typeName();
要求: 1. 成员函数
2. 不能指定返回类型 (即使如此,在实现时,你必须返回一个typeName类型的变量)
3. 不能有参数 (其实有一个默认的参数--指向当前对象的this指针)
一个例子
#include <iostream> using namespace std; class Student { private: int id; public: Student() { } Student(int ID) { id = ID; } operator int() { return id; } }; int main() { Student student(5); cout << student << endl; return 0; }
在上面这段代码中,含有语句 “cout << student << endl;”
为什么没有为 Student类 重载输出操作符函数,而编译器却没有报错呢?
因为,在输出的时候,Student对象student被自动转化为int类型的变量。而身为ostream对象的cout自然能处理int类型的变量
目前讲到的,“当前类”转换为“其他类”的例子里面,都是隐式类型转换,我们可以通过使用强制类型转换来使 “当前类” 转换为 “其他类”。
当然,在强制转换之前,我们也要像上面一样定义转换函数。
强制类型转换的句式我们也很熟悉了-- typeName (variable) 或 (typeName) variable
一些好的编程习惯:
1. 重载双目运算符时,定义为友元可以让程序更容易适应自动类型转换---两个操作数都成为了函数
参数,因此与函数原型匹配 (就是有转换函数的意思)
因为,如果操作数的类型不是当前类的类型,它可以通过 “转换函数” 转换为当前类的对象,再调
用重载的运算符函数。
2. 自动转换的隐式转换,有时候会带来一些难以发现的问题。为了保险,可以使用显式转换,比如
通过 explicit 来限定转换函数。