类型转换
我们都知道C++ 会自动处理内置类型的转换。例如,将一个标准类型变量的值赋给另一种标准类型的变量时,如果这两种类型兼容,则C++ 自动将这个值转换为接收变量的类型。
long a = 8; // int类型自动转换成long类型
double b = 11; // int类型自动转换成double类型
int c = 3.14; // double类型自动转换成int类型,但是会降低精度,变为3
int *p = 10; // 报错,无法自动转换,左边是指针类型,右边是整数,类型不兼容
int *p = (int *)10; // 正确,将10强制转换为int指针类型,将指针设置为地址10
类的自动类型转换
可以将类定义成与基本类型或另一个类相关,使得从一种类型转换为另一个种类型。
实例一
#include <iostream>
using namespace std;
class Test
{
private:
double m_sum;
public:
Test() // 默认构造函数
{
m_sum = 0;
}
Test(double sum) // 构造函数
{
m_sum = sum;
}
~Test(){} // 析构函数
Test operator+(const Test &t) const; // 重载加法运算符
friend ostream& operator<<(ostream &os, const Test &t);
};
void DisplayTest(const Test &t)
{
cout << t << endl;
}
int main()
{
Test t1(100.1);
Test t2 = 200.2; // double类型的值转换为Test类型
Test t3 = t2 + 100.1; // 100.1自动转换为Test的对象
cout << "t1: " << t1 << endl;
cout << "t2: " << t2 << endl;
cout << "t3: " << t3 << endl;
DisplayTest(t1);
DisplayTest(400.4); // 隐式转换
DisplayTest(300); // int类型先转换为double,然后在转换为Test类型
return 0;
}
Test Test::operator+(const Test &t) const
{
Test temp;
temp.m_sum = this->m_sum + t.m_sum;
return temp;
}
ostream& operator<<(ostream &os, const Test &t)
{
os << t.m_sum;
return os;
}
程序说明
Test类提供了一个接受double类型的构造函数。可以用于将double类型的值转换为Test类型。
Test(double sum);
因此,有这样合法的代码
Test t1(100.1);
Test t2 = 200.2;
Test t3 = t2 + 100.1;
DisplayTest(400.4);
DisplayTest(300);
程序将使用构造函数Test(double sum)
来创建一个临时的Test对象,并将200.2作为初始值。然后赋值给t2。这一过程称为隐式转换。
同理,在调用DisplayTest(400.4)
时,先将400.4转换为一个临时的Test对象,然后赋值给DisplayTest(const Test &t)
函数。
如果传递一个int类型的变量: DisplayTest(300);
编译器会先将int类型转换为double类型,再调用Test(double)
将其转换为Test对象。
关闭隐式转换
可以在构造函数前加上关键字explicit关闭隐式转换。
explicit Test(double sum); // 关闭隐式转换
Test t2 = 200.2; // 非法,无法进行隐式转换
Test t3 = t2 + 100.1; // 非法,无法进行隐式转换
DisplayTest(400.4); // 非法,无线进行隐式转换
Test t4 = (Test)200.2; // 合法,显示强制类型转换
Test t5 = t4 + (Test)100.1; // 合法,显示强制类型转换
DisplayTest((Test)400.4); // 合法,显示强制类型转换
如果使用了关键字explicit限定了构造函数,则它只能用于显示转换。
转换函数
转换函数用于将自定义类型转换为内置类型。
语法
operator typeName();
typeName是要转换的类型
例如
operator double(); // 要转换为double类型
注意
- 转换函数必须是类方法;
- 转换函数不能指定返回类型;
- 转换函数不能有参数。
实例二
#include <iostream>
using namespace std;
class Test
{
private:
double m_sum;
public:
Test() // 默认构造函数
{
m_sum = 0;
}
Test(double sum) // 构造函数
{
m_sum = sum;
}
~Test(){} // 析构函数
Test operator+(const Test &t) const; // 重载加法运算符
operator double() const;
operator int() const;
};
int main()
{
Test t1(100.1);
Test t2 = 200.2;
// Test t3 = t2 + 100.1; // 同时重载了加法运算符和定义了转换函数,隐式转换会产生二义性,所以需要显示转换
Test t3 = t2 + (Test)100.1; // 需要显示转换
cout << "t1: " << (double)t1 << endl; // 调用转换函数,operator double() const
cout << "t2: " << (double)t2 << endl; // 调用转换函数,operator double() const
cout << "t3: " << (int)t3 << endl; // 调用转换函数,operator int() const
int a = t1; // 调用转换函数,operator int() const
double b = t2; // 调用转换函数,operator double() const
cout << "a: " << a << endl;
cout << "b: " << b << endl;
return 0;
}
Test Test::operator+(const Test &t) const
{
Test temp;
temp.m_sum = this->m_sum + t.m_sum;
return temp;
}
Test::operator int() const
{
return (int)m_sum;
}
Test::operator double() const
{
return m_sum;
}
程序说明
- 没有重载
<<
运算符进行显示。 - 使用重载的
+
运算符时,需要显示转换。
注意
如果同时重载了加法运算符和定义了转换函数,隐式转换会产生二义性,所以需要显示转换。
Test t3 = t2 + 100.1; // 隐式转换,产生二义性
Test t3 = t2 + (Test)100.1; // 显示转换
Test t3 = (double)t2 + 100.1; // 显示转换