类的显示转换和隐式转换、explicit关键字简介
数据类型转换分为隐式转换和显式转换,根据不同的转换对象,来确定是那种类型的转换。
隐式转换
就是系统默认的、不需要加以声明就可以进行转换。
class Test{
public:
Test(int data=0) //构造函数
{
m_data = data;
}
Test(const Test &t) //拷贝构造函数
{
m_data = t.m_data;
}
Test& operator=(const Test &t) //赋值运算符重载
{
if (this!=&t)
{
m_data = t.m_data;
}
return *this;
}
~Test() //析构函数
{};
private:
int m_data;
};
void main()
{
Test t;
将100传给构造函数,构造临时对象,产生隐式转换,将整型100转换为类的对象,实际t =100是对象给对象赋值
t =100;
}
显示转换
显示转换:当系统默认转换不能转换的时候,而我们又需要把某一类型改为另一个类型,这个过程我们称之为显示转换也叫做强制转换。
class Test{
public:
Test(int data=0) //构造函数
{
m_data = data;
}
Test(const Test &t)//拷贝构造函数
{
m_data = t.m_data;
}
Test& operator=(const Test &t) //赋值运算符重载
{
if (this!=&t)
{
m_data = t.m_data;
}
return *this;
}
~Test()
{};
private:
int m_data;
};
void main()
{
Test t;
//将100强制转换为类的对象,调用构造函数+赋值运算符重载,完成赋值
t = (Test)100;
}
explicit关键字
C++提供了关键字explicit,防止类发生隐式转换,声明为explicit的构造函数不能在隐式转换中使用。
所以, 有时候在我们写下如 A = X, 这样的代码, 且恰好X的类型正好是A单参数构造器的参数类型, 这时候编译器就自动调用这个构造器, 创建一个A的对象。
这样看起来很方便。 但在某些情况下, 却违背了程序员的本意。 这时候就要在这个构造器前面加上explicit修饰, 指定这个构造器只能被明确的调用/使用, 不能作为类型转换操作符被隐含的使用。
注意:当类的声明和定义分别在两个文件中时,explicit只能写在在声明中,不能写在定义中。
class Test{
public:
explicit Test(int data = 0) //构造函数 //explicit防止类发生隐式转换
{
m_data = data;
}
Test(const Test &t)//拷贝构造函数
{
m_data = t.m_data;
}
Test& operator=(const Test &t) //赋值运算符重载
{
if (this!=&t)
{
m_data = t.m_data;
}
return *this;
}
~Test()
{};
public:
operator int() //强制类型转换
{
return m_data;
}
private:
int m_data;
};
void main()
{
Test t;
//t = 100; 会报错
t=(Test)100; //改为显示转换,不会报错
//对象如何给整数赋值
int value = t;
cout << value << endl;
}
报错: error C2679: 二进制“=”: 没有找到接受“int”类型的右操作数的运算符(或没有可接受的转换)