对于内置类型,如果两种数据类型是兼容的,C++可以自动转换,如果从更大的数转换为更小的数,可能会被截断或损失精度。
long count = 8; // int转换为long
double time = 11; // int转换为double
int side = 3.33 // double转换为int的3
C++不自动转换不兼容的类型,下面语句是非法的:
int* ptr = 8;
不能自动转换时,可以使用强制类型转换:
int* p = (int*)8;
如果某种类型与类相关,从某种类型转换为类类型是有意义的。
string str = "我是一只傻傻鸟。";
在C++中,将一个参数的构造函数用作自动类型转换函数,它是自动进行的,不需要显式的转换。
CGirl g1(8); // 常规的写法。
CGirl g1 = CGirl(8); // 显式转换。
CGirl g1 = 8; // 隐式转换。
CGirl g1; // 创建对象。
g1 = 8; // 隐式转换,用CGirl(8)创建临时对象,再赋值给g。
注意:
1)一个类可以有多个转换函数。
2)多个参数的构造函数,除第一个参数外,如果其它参数都有缺省值,也可以作为转换函数。
3)CGirl(int)的隐式转换的场景:
- 将CGirl对象初始化为int值时。 CGirl g1 = 8;
- 将int值赋给CGirl对象时。 CGirl g1; g1 = 8;
- 将int值传递给接受CGirl参数的函数时。
- 返回值被声明为CGirl的函数试图返回int值时。
- 在上述任意一种情况下,使用可转换为int类型的内置类型时。
4)如果自动类型转换有二义性,编译将报错。
将构造函数用作自动类型转换函数似乎是一项不错的特性,但有时候会导致意外的类型转换。explicit关键字用于关闭这种自动特性,但仍允许显式转换。
explicit CGirl(int bh);
CGirl g=8; // 错误。
CGirl g=CGirl(8); // 显式转换,可以。
CGirl g=(CGirl)8; // 显式转换,可以。
在实际开发中,如果强调的是构造,建议使用explicit,如果强调的是类型转换,则不使用explicit。
示例:
#include <iostream>
#include <string>
using namespace std;
// 定义一个CGirl类,用于展示类型转换
class CGirl {
public:
int age;
// 构造函数允许隐式转换
CGirl(int a) : age(a) {
cout << "CGirl created with age " << age << endl;
}
// 使用explicit关键字的构造函数防止隐式转换
explicit CGirl(double height) {
cout << "CGirl created with height " << height << endl;
}
};
void takeCGirl(CGirl g) {
cout << "Taking CGirl of age " << g.age << endl;
}
int main() {
long count = 8; // int转换为long
double time = 11; // int转换为double
int side = 3.33; // double转换为int,将被截断为3
// 使用构造函数作为隐式转换函数
CGirl g1 = 8; // 隐式转换
CGirl g2(8); // 显式构造
CGirl g3 = CGirl(8); // 显式构造
CGirl g4;
g4 = 8; // 隐式转换
// 使用explicit关键字,禁止隐式转换
// CGirl g5 = 5.9; // 这将导致编译错误,因为构造函数是explicit
CGirl g5 = CGirl(5.9); // 显式构造
// 调用接受CGirl参数的函数
takeCGirl(18); // 隐式转换
return 0;
}
在这个例子中:
CGirl(int)
允许从int
到CGirl
的隐式转换。- 使用
explicit CGirl(double)
防止从double
到CGirl
的隐式转换,但仍然允许显式转换。 - 函数
takeCGirl
接受一个CGirl
对象,演示了向该函数传递int
类型时,如何自动调用构造函数来完成类型转换。