一、类型转换
1.1、标准类型转换
将一个标准类型变量的值赋给另一种标准类型的变量时,如果这两种类型兼容,则C++自动将这个值转换为接收变量的类型。
比如long,double和int的转换,都表示数字,其中double类型赋值给int类型变量将会降低精度。例如:
double time = 3.3;
int side = time;
如果两种类型不兼容,C++则不会自动转换。例如:
int * p = 10; //非法语句
计算机内可能使用整数来表示地址,但是从概念上理解,指针和整数完全不同,所以C++不会自动转换这两种不兼容的类型。
但是可以使用强制类型转换,例如:
int * p = (int*) 10;
这里是可以的,因为(int*)和p都是指针,上述语句将10强制转换为int类型指针。
1.2、自定义类型转换
可以将类定义成与基本类型或另一个类相关,使得从一种类型转换为另一种类型是有意义的。此时开发人员可以指示C++如何自动进行转换,或通过强制类型转换来完成。
在C++中,接受一个参数的构造函数为将类型与该参数相同的值转换为类提供了指导,且只有接受一个参数的构造函数才能作为转换函数,接受两个没有默认值的参数则无法用于类型转换。例如:
Stonewt (double lbs); //接受一个参数,可以用于类型转换。
Stonewt (int stn, double lbs);//接受两个没有默认值的参数,不可以用于类型转换
Stonewt (int stn, double lbs = 1.1);//第二个参数有默认值,可以用于int类型的转换。
上述构造函数用于将double类型的值转换为Stonewt类型。例如:
Stonewt myCat;
myCat = 19.6; //隐式转换,自动进行,不需要显式的强制类型转换。
除了以上的赋值语句以外,还有如下几种情况可以完成隐式转换。
1、将Stonewt对象初始化为double值时。
2、将double值传递给接受Stonewt参数的函数时。
3、返回值被声明为Stonewt的函数试图返回double值时。
4、在上述几种情况下,使用可转换为double类型的标准类型时(其他类型先转换为double,再转换成自定义类型)
Stonewt bo(700);
bo = 230;
需要注意用于类型转换的单个参数的构造函数只能有一个,不能导致二义性的存在,否则编译器将会拒绝隐式自动转换语句。例如
Stonewt(long a);
Stonewt(double b);
Stone c(300);
此时int可被转换为long,也可转换为double,因此调用存在二义性,编译器将会拒绝隐式转换。
1.3、explicit关键字
看起来将构造函数作为自动类型转换函数很方便,但是这种自动的特性并非总是合乎需要,因为会导致一些意外的类型转换。所以C++增加了关键字explicit用于关闭这种自动特性。例如:
explicit Stonewt (double lbs); //不允许隐式的自动转换
这将关闭使用时发生的隐式转换,但仍然允许显式转换,即显式强制类型转换。
Stonewt myCat;
myCat = Stonewt (19.6);
myCat = (Stonewt)19.6;
经验表明,不要依赖于这种隐式的转换方法。代码在以后的维护中将出现未知的错误。
1.4、转换函数
可以通过带单个参数的构造函数,将某种类型转换为类类型,如果需要进行相反的转换,将类类型转换为某种类型,则需要用户定义的强制类型转换函数。
转换函数定义形式如下:
operator typeName();
1、转换函数必须是类方法;
2、转换函数不能指定返回类型;typeName指出了要转换成的类型,因此不再需要指定返回类型
3、转换函数不能有参数;因为是类方法所以要通过类对象来调用,从而告知函数要转换的值,所以不需要参数。
比如,将类类型转换为double或int类型的函数如下:
operator int();
operator double();
当定义了多个转换函数时,但是仍可以用显式强制类型转换来指出要使用哪个转换函数。
Stonewt gone = (double)p;
Stonewt gone = (int)p;
在C++11中,关键字explicit可以用于转换函数,避免隐式转换。
class Stonewt
{
...
explicit operator int() const;
explicti operator double() const;
};
这样需要强制转换时将会调用这些运算符。
也可以用一个功能相同的非转换函数替换该转换函数,只有在被显式调用的时候该非转换函数才会被执行。例如:
int Stonewt::Stone_to_Int() { return (int ) pounds};
开发过程中应该尽可能的避免隐式转换函数。通常,只有选择仅在被显式调用的时候才会执行的函数。