Skip to content

Latest commit

 

History

History
101 lines (76 loc) · 2.63 KB

File metadata and controls

101 lines (76 loc) · 2.63 KB

转换函数

上一篇我们聊了类的转换,C++允许通过构造函数进行隐式类型转换。

那我们自然而然产生一个问题:这样的转换可逆吗?我们有没有办法把一个类的对象再转换回基本变量类型呢?

比如:

Time t(14);
int x = t;

这是可以的,不过不是使用构造函数。构造函数只能用于从某种类型到类类型的转换,要进行相反的转换需要使用 C++中的一种特殊运算符函数——转换函数。

转换函数是用户定义的强制类型转换,可以使用强制类型转换的语法来使用。加入我们定义了Time类的转换函数,我们可以使用如下的转换:

Time t(14);
int x = int(t);
int y = (int) t;

那么如何创建转换函数呢?其实转换函数本质上也是一种运算符重载,要转换为typeName类型,需要使用这种形式的转换函数:

operator typeName();

并且还有几个条件:

  • 必须是类方法
  • 不能指定返回类型
  • 不能有参数

加上转换类型之后,Time定义如下:

class Time {
 	private:
    	int minutes;
    public:
    	Time();
    	Time(int m) {
			minutes = m;
		}
    	operator int() const;
    	operator double() const;
};

虽然转换函数没有声明返回类型,但是我们一样需要返回所需的值。我们再来看下实现的代码:

Time::operator int() const {
    return minutes;
}

Time::operator double() const {
    return double(minutes);
}

到这里还没有结束,还有一个很有趣的问题,假设我们使用cout来输出Time对象,那么请问输出的结果会是int还是double呢?

Time t(14);
cout << t << endl;

答案是都不会,编译器会报错。因为cout时没有指定类型,所以编译器会报错使用了二义性(ambiguous)转换。但如果我们去掉一个转换函数,只保留一个,则不会有二义性,可以运行。

同样,我们在赋值的时候也会存在二义性:

long t = Time(14);

解决办法是在赋值的时候使用强制类型转换来指出要使用哪个转换函数:

Time t(14);
int x = (int) t;
int y = double(t);

和类的转换一样,转换函数有的时候也会有意外情况。为了避免在我们意料之外进行转换,C++11 对转换函数也支持了explicit关键字,加上了关键字之后,只有强制转换时才会调用这些转换函数。

class Time {
 	private:
    	int minutes;
    public:
    	Time();
    	Time(int m) {
			minutes = m;
		}
    	explicit operator int() const;
    	explicit operator double() const;
};