学过c++肯定都知道,c++基本类型之间的转换,char,int,float,double之间可以相互转换,有隐式转换和强制类型转换。
现在就来说说类的自动转换和强制类型转换。
先来看一个例子:
#include <iostream> #include <cmath> using namespace std; double pi = acos(-1.0); class circle { private: double radius;/**< 圆半径 */ public: circle(double r) { radius = r; } circle() { radius = 0; } double GetArea()/**< 获取面积 */ { return pi * radius * radius; } }; int main() { circle c = 5.0;/**< 声明一个圆的对象 */ cout<<"area:"<<c.GetArea()<<endl; return 0; }
#include <iostream> #include <cmath> using namespace std; double pi = acos(-1.0); class circle { private: double radius;/**< 圆半径 */ public: circle(double r) { radius = r; } circle() { radius = 0; } double GetArea()/**< 获取面积 */ { return pi * radius * radius; } operator double () { return radius; } }; int main() { circle c = 5.0;/**< double转换成circle */ cout<<"area:"<<c.GetArea()<<endl; double r = c;/**< circle转换成double */ cout<<"radius:"<<r<<endl; return 0; }
/**<
运行结果:area:78.5398
程序正常通过。
对于circle c = 5.0;
可以看出直接将double类型的赋给了circle类对象。
程序将使用构造函数circle(double)来创建一个临时的circle对象,并将5.0最为初始值。再讲临时对象赋给c。这一过程就是double
类型隐式转换成circle类对象。是由程序自动完成的。
(需要注意的是,只有当构造函数有一个参数时才能作为转换函数,除非其他参数都带有默认值。
感兴趣的可以自己试一试。)
也可以通过显示转换来完成这一过程,
比如 circle c = (circle)5.0;
或者 circle c = circle(5.0)。
到这,就可能会想了,竟然double类型可以转换成circle类型,那么circle类型可以转换成double类型嘛。
c++提供了这样的机制,
只需要我们使用下面形式的转换函数:
operator typename()
例如:operator double()
需要注意的是:转换函数必须是类方法;
转换函数不能指定返回类型(typename就是指定返回类型);
转换函数也不能带参数,是通过类对象来调用的。
下面就来看看它的使用:
*/
/**<
运行结果:
area:78.5398
radius:5
*/
这都是由程序通过隐式转换自动完成的。
对于转换构造函数和转换函数都有其优缺点:可能用户不希望进行转换时,转换函数也可能进行转换。
现在假设circle中存在operator int(){ return (int)radius; }
然后粗心的你又不小心写下了下面的代码:
int arr[10];
circle tmp = 5.5;
int Tmp = 0;
...
cout<<arr[tmp]<<endl;程序也能正常通过,但结果可能就是不对。这种错误可能很难观察到。
所以应谨慎使用隐式转换函数。通常,最好的选择是使用显示转换。
在转换构造函数和转换函数前加上explicit关键字就可以防止隐式转换,程序员写代码时必须通过强制转换才行。