自定义类的类型转换
C++中,不同类型之间在赋值时可能发生自动类型转换,例如
int x = 2.4;
这个语句将会把2.4转换成int
类型然后再赋值给x
,这一过程发生了自动类型转换。
原始类型向自定义类的转换(使用构造函数)
对于用于自己定义的类,C++也可以进行自动类型转换,下面是一个例子:
class Stock{
private:
double price;
public:
Stock(double p){
price = p;
}
Stock();
void show(){
cout << "Stock price is: " << price << endl;
}
};
Stock s = 3.4; //发生了自动类型转换
s.show();
在该例子中,直接将double
类型的值赋给了Stock
类型的变量,但是编译器利用Stock
类的构造函数进行了自动类型转换。
注意,只有构造函数只接受一个参数的时候,该构造函数才能被用来进行自动类型转换,但是为接收多个参数的构造函数设置默认值也可以使该函数可以被用来转换类型。
有些时候,我们可能不希望构造函数被用来自动转换类型,这样就可以使用explicit
关键字来指定,该构造函数不能用来隐式类型转换,而只能用来显式类型转换,例如:
class Stock{
private:
double price;
public:
explicit Stock(double p){
price = p;
}
Stock();
void show(){
cout << "Stock price is: " << price << endl;
}
};
Stock s = (Stock)3.4; //只能用于显式类型转换
s.show();
自定义类向原始类型的转换(使用转换函数)
上面介绍的方法是将自定义的类转换成原始类型,编译器会根据=
右边的数据类型,调用左边类的相应构造函数,以完成由原始类型向自定义类的转换。但是当反过来(原始类型在左边,自定义类在右边)的时候,原始类型是没有构造函数的,这时就不能通过构造函数的方式来实现数据类型的转换。
C++定义了一个另外一个实现方式,就是转换函数,其基本语法为:
operator typename();
关于转换函数有几个需要注意的地方:
- 转换函数的声明必须在类的声明中。
- 转换函数没有返回值类型和参数,因为
typename
表示返回类型,而其声明位置表示参数,即在哪个类中声明的就以该类为参数。 - 转换函数的声明中没有返回类型,但是在函数的定义中必须返回一个值,这个返回值是转换后的结果。
下面是一个实例:
class Stock{
private:
double price;
public:
Stock(double p){
price = p;
}
Stock();
//函数签名没有返回类型和参数列表,但必须返回一个值作为类型转换的结果
operator double(){return price;}
};
Stock s = (Stock)3.4;
//调用转换函数,也可以让编译器自己调用,即隐式转换 double res = s;
double res = double(s);
cout << res << endl;
跟构造函数方式类似,也可以使用explicit
关键字将该转换函数声明成只能显式调用,防止有些时候意想不到的隐式转换。
上述两种实现方法之间的关系
首先需要明白的是,转换的过程是从一种类型到另一种类型,在这里为了表述方便,将第一种类型称为起点类型
,而将第二种类型称为目标类型
。
在实际应用中,使用上述两种方法中的哪一种是根据你准备将转换函数的实现放在哪个类型中决定的。如果在起点类型
中实现转换,就使用转换函数
的方式;相反,如果要将实现放在目标类型
中,则需要使用构造函数的形式。
在实现两个自定义类型之间的类型转换的时候,可以使用上述任意两种方式,是需要将上述实现中的原始类型描述符
改成自定义类型描述符
即可。
而当转换的一方为原始类型
时,由于不能将转换的实现放在原始类型
中,所以必须将其放在自定义类型
中。