C++:类运算中的类型转换:类对象转数据,数据转类对象

我们知道直接把一个对象拿来与数据进行计算是不可以的,除非我们在类中定义了重载的运算符函数。今天来讲讲使类对象与一个普通数据进行加减等运算的方法,以及对类对象进行强制数据类型转换的方法。

类对象与普通数据进行加减等运算,可以定义重载运算符函数,也可以定义转换构造函数。转化构造函数的原理就是,把要与类对象进行运算的数据转换为一个与其同类的对象,再通过定义一个形参为两个类对象的,返回值为类或类的引用的运算符重载函数来实现类与类的计算(有一说一,既然说到底还是要定义运算符重载函数,为啥不直接定义类与数据相加的运算符重载函数呢?)

对类对象进行强制类型转换,按规则来说也是不行的。但是我们可以通过类型转换函数(类的成员函数,无返回类型定义,无参数)来操作,它的定义方式:

operator 目标类型(){

函数体部分

}

来看示例程序,里面包含了类型转换函数,转换构造函数,类对象对数据的运算符重载函数,类与类之间的运算符重载函数:

#include<iostream>
#include<string>
using namespace std;
class Complex {
private:
	double real;
	double imag;
public:
	Complex(double r, double i) //构造函数
	{
		real = r;
		imag = i;
	}
	Complex(Complex& m)//拷贝构造函数,单纯写出来看看,其实本例直接用默认生成的就足够了
	{
		real = m.real;
		imag = m.imag;
	}
	Complex(double a) //转换构造函数,如果想要实现复数与double类型相加,调用本函数使double数据变为一个Complex的对象
	{                 //特点:把数据转换为对象,实际上这个功能,自己定义一个+号运算符重载函数也可以,只不过要定义成两个友元函数
		real = a;
		imag = 0;
	}
	friend Complex& operator+(Complex& ,double);//注意,这个的形参是类的对象的引用,在函数体里对传入数据的操作同样会改变实际的外部对象 
	friend Complex& operator+(double, Complex);//注意,这个的形参是类的对象,所以无论函数体对传入的对象做什么,实际的对象不会变
	operator double() //类型转换函数(只能定义为成员函数),不带参数,没有返回类型,operator后面指明要将该类对象转换为什么类型数据
	{                 //特点:把对象转换为数据
		return real;
	}
	friend Complex& operator+(Complex A, Complex B) {
		A.real += B.real;
		A.imag += B.imag;
		return A;
	}
	void show() //以复数形式打印
	{
		if (imag > 0)
			cout << real << "+" << imag << "i" << endl;
		else if (imag == 0)
			cout << real << endl;
		else cout << real << imag <<"i"<< endl;
	}
};
Complex& operator+(Complex& A, double B) {
	Complex temp(A);//重建一个对象temp保存A的数据成员,使得A不会因为运算而改变
	temp.real = A.real + B;
	temp.imag = A.imag;
	return temp;
}
Complex& operator+(double B, Complex A) {
	A.real += B;//由于传入的不是对象的引用,故不会改变实际外部对象的值,所以不用像上面那样建立temp来保存数据
	return A;
}
int main() {
	Complex test1(2.3, 9), test2(4.8, 10), test3(1.5, 3.1), test4(0, 0);
	cout << "先看看四个复数对象:\n";
	test1.show();
	test2.show();
	test3.show();
	test4.show();
	cout << "使用相加运算符重载函数,整数在后:test4=test1+3.0=";
	test4 = test1 + 3.0;
	test4.show();
	cout << "使用相加运算符重载函数,整数在前:test4=3.0+test2=";
	test4 = 3.0 + test2;
	test4.show();
	cout << "使用转换构造函数:test4=test1+3=";
	Complex com1(3.0);//调用转换构造函数使数据变为对象,再调用形参为两个Complex&类型的相加运算符重载函数进行加法计算
	test4 = test1 + com1;
	test4.show();
	cout << "使用转换构造函数:test4=3+test3=";
	test4 = com1 + test3;
	test4.show();
	cout << "使用类型转换函数,结果应为real+数据:3.0+(double)test1=" << 3.0 + (double)test1 << endl;
	cout << "使用类型转换函数,结果应为real+数据:(double)test3+3.0=" << (double)test3 + 3.0 << endl;
}

运行结果:

先看看四个复数对象:
2.3+9i
4.8+10i
1.5+3.1i
0
使用相加运算符重载函数,整数在后:test4=test1+3.0=5.3+9i
使用相加运算符重载函数,整数在前:test4=3.0+test2=7.8+10i
使用转换构造函数:test4=test1+3=5.3+9i
使用转换构造函数:test4=3+test3=4.5+3.1i
使用类型转换函数,结果应为real+数据:3.0+(double)test1=5.3
使用类型转换函数,结果应为real+数据:(double)test3+3.0=4.5

这里定义两个类对象加数据的运算符重载函数,是为了充分考虑数据+对象,对象+数据的表达式都能成立;

再注意一点:由于我的程序中自己定义了拷贝构造函数,它的形参是类的引用,故我们定义的运算符重载函数和转换构造函数都要以类的引用为函数类型,否则test4=3.0+test1,test4=com1+test1这样的语句会出现错误,我们不妨来看一下,把运算符重载函数的返回类型从类的引用改为类的对象会怎么样:

#include<iostream>
#include<string>
using namespace std;
class Complex {
private:
	double real;
	double imag;
public:
	Complex(double r, double i) //构造函数
	{
		real = r;
		imag = i;
	}
	Complex(Complex& m)//拷贝构造函数,单纯写出来看看,其实本例直接用默认生成的就足够了
	{
		real = m.real;
		imag = m.imag;
	}
	Complex(double a) //转换构造函数,如果想要实现复数与double类型相加,调用本函数使double数据变为一个Complex的对象
	{                 //特点:把数据转换为对象,实际上这个功能,自己定义一个+号运算符重载函数也可以,只不过要定义成两个友元函数
		real = a;
		imag = 0;
	}
	friend Complex/*&省略掉*/ operator+(Complex& ,double);//注意,这个的形参是类的对象的引用,在函数体里对传入数据的操作同样会改变实际的外部对象 
	friend Complex/*&省略掉*/operator+(double, Complex);//注意,这个的形参是类的对象,所以无论函数体对传入的对象做什么,实际的对象不会变
	operator double() //类型转换函数(只能定义为成员函数),不带参数,没有返回类型,operator后面指明要将该类对象转换为什么类型数据
	{                 //特点:把对象转换为数据
		return real;
	}
	friend Complex/*&省略掉*/ operator+(Complex A, Complex B) {
		A.real += B.real;
		A.imag += B.imag;
		return A;
	}
	void show() //以复数形式打印
	{
		if (imag > 0)
			cout << real << "+" << imag << "i" << endl;
		else if (imag == 0)
			cout << real << endl;
		else cout << real << imag <<"i"<< endl;
	}
};
Complex/*&省略掉*/ operator+(Complex& A, double B) {
	Complex temp(A);//重建一个对象temp保存A的数据成员,使得A不会因为运算而改变
	temp.real = A.real + B;
	temp.imag = A.imag;
	return temp;
}
Complex/*&省略掉*/operator+(double B, Complex A) {
	A.real += B;//由于传入的不是对象的引用,故不会改变实际外部对象的值,所以不用像上面那样建立temp来保存数据
	return A;
}
int main() {
	Complex test1(2.3, 9), test2(4.8, 10), test3(1.5, 3.1), test4(0, 0);
	cout << "先看看四个复数对象:\n";
	test1.show();
	test2.show();
	test3.show();
	test4.show();
	cout << "使用相加运算符重载函数,整数在后:test4=test1+3.0=";
	test4 = test1 + 3.0;
	test4.show();
	cout << "使用相加运算符重载函数,整数在前:test4=3.0+test2=";
	test4 = 3.0 + test2;
	test4.show();
	cout << "使用转换构造函数:test4=test1+3=";
	Complex com1(3.0);//调用转换构造函数使数据变为对象,再调用形参为两个Complex&类型的相加运算符重载函数进行加法计算
	test4 = test1 + com1;
	test4.show();
	cout << "使用转换构造函数:test4=3+test3=";
	test4 = com1 + test3;
	test4.show();
	cout << "使用类型转换函数,结果应为real+数据:3.0+(double)test1=" << 3.0 + (double)test1 << endl;
	cout << "使用类型转换函数,结果应为real+数据:(double)test3+3.0=" << (double)test3 + 3.0 << endl;
}

运行结果为:

先看看四个复数对象:
2.3+9i
4.8+10i
1.5+3.1i
0
使用相加运算符重载函数,整数在后:test4=test1+3.0=5.3
使用相加运算符重载函数,整数在前:test4=3.0+test2=7.8
使用转换构造函数:test4=test1+3=5.3
使用转换构造函数:test4=3+test3=4.5
使用类型转换函数,结果应为real+数据:3.0+(double)test1=5.3
使用类型转换函数,结果应为real+数据:(double)test3+3.0=4.5

发现了吗,虚数部分不见了,故而要么自己不定义拷贝构造函数,要么小心注意。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值