1、普通类型通过隐式转换为类类型:
类声明中只接受一个参数的构造函数,或接受多个参数但其余参数均有默认值时可以进行隐式类型转换,例子:
// .h
Class Stone{
private:
double abc;
public:
Stone() {}
Stone(double para1){abc = para1;}
Stone_show(){cout<<abc;}
};
//.cpp
Stone s1;
s1 = 15.2; //首先调用Stone(double)生成临时对象,然后利用默认赋值运算符对s1进行赋值,这一过程称为隐式转换。
隐式转换可能不是程序想要的,为避免隐式转换的发生,C++提供了explicit
关键字,如下:
//.h
Class Stone{
...
explicit Stone(double para1){abc = para1;}
...
};
//.cpp
Stone s1 = 15.2; //报错
Stone s1 = Stone(15.2); //显式转换可以
Stone s1 = (Stone)15.2; //显式转换可以
若在声明中构造函数使用了explicit
,则Stone(double)
只能用于显式类型转换,未使用explicit
,则在一下几种情况会进行隐式类型转换:
1、将Stone对象初始化为double值;
2、将double值赋给Stone对象时;
3、将double值作为参数传给Stone对象作参数的函数时;
4、函数返回值为Stone,但将double值返回时;
5、上述情况中,使用可转为double的其他内置类型时,如int。
//.cpp
void show(const Stone& a){
a.Stone_show();
}
Stone s1 = 20; // int先转为double,然后调用隐式转换。
show(20); // 20先转为double,然后隐式转换,变成show()函数要求的Stone类型
2、类对象通过定义的转换函数转换为普通类型:
即为实现如下转换:
Stone s1(20.1);
double db1 = s1; //此过程需要通过C++运算符函数——转换函数进行
转换函数operator typename();
需求:
1、转换函数必须是类方法;
2、转换函数不能指定返回类型;
3、转换函数不能有参数。
//.h
Class Stone{
...
operator double () const {return abc}
};
//.cpp
Stone s1;
double res = double(s1); //显式转换
double res = (double)s1; //显式转换
double res = s1; //隐式转换
a) 转换函数中typename指出了要转换的类型,因此不需要指定返回类型;因为是类方法,需要类对象调用,因此函数不需要参数。
b) 也可通过将该转换函数声明为explicit
禁止隐式转换。
c) 当定义了两个转换函数时,如转为int和double两个,调用隐式转换时存在二义性,编译失败,但显式转换依然可以。
参考资料:C++ Primer Plus 11.6节
总结:
1、当类的构造函数只接受一个参数且未声明为explicit
时可进行隐式转换,将参数类型转换为类类型,在将与类中构造函数参数类型相同的值赋给对象时,自动调用。
2、通过自定义转换函数operator typename();
,可将类类型转换为其他指定类型,也可通过explicit
关键字禁止隐式转换,将类对象赋值给typename
变量时,自动调用。
3、经验表明,最好不要依赖隐式转换。
4、隐式类型转换只针对函数中调用参数,调用者不能转换。