C++ 显示转换关键字explicit详解
想要理解显示转换,首先得明白与之对应得隐式转换是什么。
implicit隐式转换
隐式转换关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式),且不显示出来,因此常常被我们所忽略。下面详细讲解隐式转换得过程
假如一个类A的构造函数是A(int i),
则在变量声明的时候,既用A a(1);,
又可以使用隐式转换A a=1;这一步中间省略的操作为A temp(1); A a=temp;
因此1可以通过构造函数A(int i)转换为一个类A的对象。(隐含的类型转换操作符)
具体过程见如下代码所示
//CxString 隐式构造函数
class CxString
{
public :
char* _pstr;
int _size;
CxString(int size)
{
_size = size;
_pstr = (char*)malloc(size + 1);
memset(_pstr, 0, size + 1);
}
CxString(const char* p)
{
int size = strlen(p);
_pstr = (char*)malloc(size + 1);
strcpy(_pstr, p);
_size = size;
}
};
CxString string1(24); // 这样是OK的, 为CxString预分配24字节的大小的内存
//编译会有一个隐式转换:将该构造函数对应数据类型的数据转换为该类对象.
//CxString temp(10);
//CxString string2 = temp;
// 所以这样是OK的, 为CxString预分配10字节的大小的内存
CxString string2 = 10;
CxString string3; // 这样是不行的, 因为没有默认构造函数, 错误为: “CxString”: 没有合适的默认构造函数可用
CxString string4("aaaa"); // 这样是OK的
CxString string5 = "bbb"; // 这样也是OK的,
CxString string6 = 'c'; // 这样也是OK的, 其实调用的是CxString(int size), 且size等于'c'的ascii码
string1 = 2; // 这样也是OK的, 为CxString预分配2字节的大小的内存
string2 = 3; // 这样也是OK的, 为CxString预分配3字节的大小的内存
string3 = string1; // 这样也是OK的, 至少编译是没问题的, 但是如果析构函数里用free释放_pstr内存指针的时候可能会报错, 完整的代码必须重载运算符"=", 并在其中处理内存释放
上述代码中,CxString string6 = ‘c’; 其实就是隐式转换所带来的弊端,使得对象声明的时候开辟了错误大小的初始空间。C++为我们简化操作,获得方便得同时,也会出现一些与之对应问题。而因为这个问题引入explicit,显示变换。
explicit显示转换
C++中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的
//CxString 显示构造函数
class CxString2
{
public:
char* _pstr;
int _size;
explicit CxString2(int size)
{
_size = size;
_pstr = (char*)malloc(size + 1);
memset(_pstr, 0, size + 1);
}
CxString2(const char* p)
{
int size = strlen(p);
_pstr = (char*)malloc(size + 1);
strcpy(_pstr, p);
_size = size;
}
};
//显示构造函数不会进行隐式转换 顾这样写是错误的
CxString2 string7 = 10;
//只能这样进行初始化
CxString2 string8(10);
string8 = 10; //这样写也不行,因为已经不允许进行隐式变换
explicit关键字的作用就是防止类构造函数的隐式自动转换.