C++类对象之间的类型转换和重载

类对象和其他类型对象的转换

转换场合有:

  赋值转换

  表达式中的转换

  显式转换

  函数调用

传递参数时的转换 转换方向有:

  由定义类向其他类型的转换

  由其他类型向定义类的转换

#include <math.h>

#include <iostream>
using std::cout;
using std::endl;

class Complex
{
public:
	Complex(double dreal, double dimag)
	: _dreal(dreal)
	, _dimag(dimag)
	{}

	void display() {
		cout << _dreal << " + " << _dimag << "i" << endl;
	}

	friend std::ostream & operator<<(std::ostream & os, const Complex & rhs);
private:
	double _dreal;
	double _dimag;
};

std::ostream & operator<<(std::ostream & os, const Complex & rhs)
{
	if(rhs._dreal == 0 && rhs._dimag != 0)
		os << rhs._dimag << "i";
	else {
		os << rhs._dreal;
		if(rhs._dimag > 0)
			os << " + " << rhs._dimag << " i";
		else if (rhs._dimag < 0)
			os << " - " << rhs._dimag * (-1) << " i";
	}
	return os;
}

class Point
{
public:
	Point(int ix = 0, int iy = 0)
	: _ix(ix)
	, _iy(iy)
	{
		cout << "Point(int=0, int=0)" << endl;
	}


	//由自定义类型向其他类型进行转换
	//
	//类型转换函数
	//1. 必须是成员函数
	//2. 没有返回值类型
	//3. 在函数体内必须用return 语句以传值方式返回一个目标类型的变量(对象)
	//4. 没有形参
	//5. 一般情况下,不要使用它, 因为它违反了常规思维方式

	operator int()
	{	
		cout << "operator int()" << endl;
		return _ix;	
	}

	operator double()
	{	
		cout << "operator double()" << endl;
		return _ix * _iy;	
	}

	operator Complex()
	{
		cout << "operator Complex()" << endl;
		return Complex(_ix, _iy);
	}

	void print() const
	{
		cout << "(" << _ix
			 << "," << _iy
			 << ")" << endl;
	}

	friend std::ostream & operator<<(std::ostream & os, const Point & rhs);
private:
	int _ix;
	int _iy;
};

std::ostream & operator<<(std::ostream & os, const Point & rhs)
{
	os << "(" << rhs._ix
	   << "," << rhs._iy
	   << ")";
	return os;
}

 
int main(void)
{
	Point pt1(1, 2);
	
	int x = pt1;
	cout << "x = " << x << endl;

	double dvalue = pt1;
	cout << "dvalue = " << dvalue << endl;

	Complex cx = pt1;
	cout << "cx = " << cx << endl;

	return 0;
}

  

由其他类型向定义类的转换

  • 由其他类型(如int、double)等向自定义类的转换是由构造函数来实现的,只有当类的定义和实现中提供了合适的构造函数时,转换才能通过。什么样的构造函数才是合适的构造函数呢?主要有以下几种情况,为便于说明,假设由int类型向自定义point类转换:
    • point类的定义和实现中给出了仅包括只有一个int类型参数的构造函数 Point pt1 = 5;
    • point类的定义和实现中给出了包含一个int类型参数,且其他参数都有缺省值的构造函数
    • point类的定义和实现中虽然不包含int类型参数,但包含一个非int类型参数如float类型,此外没有其他参数或者其他参数都有缺省值,且int类型参数可隐式转换为float类型参数。
  • 在构造函数前加上关键字explicit可以关闭隐式类型转换 
//9-12 由其他类型转换到自定义类型
#include <iostream>
using namespace std;

class point;

class anotherPoint //anotherPoint类定义
{
private: //private成员列表
	double x;
	double y;

public:
	anotherPoint(double xx = 1, double yy = 1) //构造函数,带缺省参数值
	{
		x = xx;
		y = yy;
	}

	void print()			//输出函数,点的信息
	{
		cout << "( " << x << " , " << y << " )";
	}

	friend class point;		//使point类成为本类的友元类, 这样point
							//类就可以访问anotherPoint 类的private变量了
};

class point		//point类定义
{
private:		//private成员列表
	int xPos;
	int yPos;

public:
//	explicit //如果在构造函数前加上explicit, 就不允许 point pt1 = 5这种隐式转换了
	point(int x = 0, int y = 0)	//构造函数,带缺省参数,两个int型变量
	{
		xPos = x;
		yPos = y;
	}

	point(anotherPoint aP)		//构造函数,参数为anotherPoint类对象
	{
		xPos = aP.x;			//由于point类是anotherPoint类的友元类,
		yPos = aP.y;			//因此这里可以访问anotherPoint的私有变量x和y
	}

	void print()				//输出函数,点的信息
	{
		cout << "( " << xPos << " , " << yPos << " )" << endl;
	}
};

int main()
{
	//1. 将int类型数字5转换成point类型
	point p1;			//创建point类对象p1,采用带缺省参数的构造函数,即x=0、y=0
	cout << 5 << " 转换成 ";
	p1 = 5;				//等价于p1=point(5,0);
	p1.print();			//输出点p1的信息
	
	//2. 将double类型变量dX转换成point类型
	double dX = 1.2;	//声明一个double变量dX
	cout << dX << " 转换成 ";
	p1 = dX;			//等价于p1=point(int(dX),0)
	p1.print();			//输出点p1的信息
	
	//3. 将anotherPoint类型转换成point类型
	anotherPoint p2(12.34, 56.78);	//创建anotherPoint类的对象p2
	p2.print();
	cout << " 转换成 ";
	p1 = p2;			//等价于p1=point(p2);
	p1.print();			//输出点p1的信息

	//4. 测试在point构造函数前加上explicit以阻止隐性转换的情况
	
	return 0;
}

  

类型转换函数

  • 可以通过operator int()这种类似操作符重载函数的类型转换函数实现由自定义类型向其他类型的转换。如将point类转换成int类型等。
  • 在类中定义类型转换函数的形式一般为:

    operator 目标类型名();

  • 有以下几个使用要点:
    • 转换函数必须是成员函数不能是友元形式
    • 转换函数不能指定返回类型但在函数体内必须用return语句以传值方式返回一个目标类型的变量
    • 转换函数不能有参数
//类型转换函数(由类转换成其他类型)
#include <iostream>
using namespace std;

class point;
ostream & operator<<(ostream &os, const point &pt);

class anotherPoint		//anotherPoint类定义
{
private:			//private成员列表
	double x;
	double y;

public:
	anotherPoint(double xx = 1.11, double yy = 1.11)//构造函数,带缺省参数值
	{
		x = xx;
		y = yy;
	}

	void print()	//成员函数,输出点的信息
	{
		cout << "( " << x << " , " << y << " )" << endl;
	}
};

class point		//Point类定义
{
private:		//private成员列表
	int xPos;
	int yPos;

public:
	point(int x = 0, int y = 0)		//构造函数,带缺省参数值
	{
		xPos = x;
		yPos = y;
	}

	void print()	//成员函数,输出点的信息
	{
		cout << "( " << xPos << " , " << yPos << " )" << endl;
	}

	friend ostream & operator<<(ostream &os, const point &pt);	// 重载<<运算符

	operator int()	//定义Point向int型的转换函数int()
	{
		return xPos;
	}

	operator double()	//定义Point向double型的转换函数double()
	{
		return xPos * yPos;
	}

	operator anotherPoint()	//定义Point向anotherPoint型的转换函数anotherPoint()
	{
		return anotherPoint(xPos, yPos);
	}
};

ostream & operator<<(ostream &os, const point &pt)
{
	os << (pt.xPos * 100);
	return os;
}

int main()
{
	point p1(4, 5);			//声明一个point类变量p1
	p1.print();

	//1. point转换成int
	int x1 = p1;		//p1赋值给一个int型变量,point中的转换函数int()被隐式调用
	cout << x1 << endl;

	//2. point转换成double
	double dX = p1;	     //p1赋值给一个double型变量,point中的转换函数double()被隐式调用
	cout << dX << endl;

	//3. point转换成anotherPoint
	anotherPoint p2;		//声明anotherPoint类对象p2,构造函数采用缺省值
	p2 = p1;		//p1赋值给p2,point中的转换函数anotherPoint()被隐式调用
			//等价于p2=anotherpoint(p1.xPos,p1.yPos)
	p2.print();		//看p2是否修改成功

	return 0;
}