运算符重载实验(超基础和干货的代码训练)

T1.Purpose of the experiment

Master the basic syntax of operator overloading.
Skillfully use the function with the same name to complete the same basic operation.

T2.Experiment content

[Experiment topic 1]

一。复数类运算符示例程序:
#include
#include
using namespace std;
class Complex{
double Real,Image ;
public :
Complex(double r=0.0, double i=0.0):Real®,Image(i){}
Complex(const Complex &com)
{
Real=com.Real ; Image=com.Image ;
}
void Print()
{cout<<“Real=”<<Real<<’\t’<<“Image=”<<Image<<’\n’;
}
Complex operator+(Complex); //重载+运算符函数
Complex operator+(double); //重载+运算符函数
Complex operator=(Complex); //重载=运算符函数
Complex operator+=(Complex); //重载+=运算符函数
double abs(void); //求绝对值函数
Complex operator*(Complex); //重载运算符函数
Complex operator/(Complex); //重载/运算符函数
};
Complex Complex::operator+(Complex c)
{//重载+
Complex Temp(Real+c.Real , Image+c.Image) ;
return Temp ;
}
Complex Complex::operator+(double d)
{ //重载+
return Complex(Real+d , Image);
}
Complex Complex::operator+=(Complex c)
{//重载+ =
Complex temp; //为了返回Complex类型的值,使+=可以连续使用
temp.Real=Real+c.Real; temp.Image=Image+c.Image;
Real=temp.Real; Image=temp.Image;
return temp;
}
Complex Complex::operator=(Complex c)
{//重载=
Complex temp; //定义temp为可返回Complex类型值,使=可连续使用
temp.Real=c.Real; temp.Image=c.Image;
Real=temp.Real; Image=temp.Image;
return temp;
}
double Complex::abs(void)
{//求绝对值函数
return sqrt(Real
Real+ImageImage);
}
Complex Complex::operator
(Complex c)
{//重载*
return Complex(Realc.Real-Imagec.Image ,Realc.Image+c.RealImage);
}

Complex Complex::operator/(Complex c)
{ //重载/
double d=c.Realc.Real+c.Imagec.Image ;
return Complex((Realc.Real+Imagec.Image)/d , (Imagec.Real-Realc.Image)/d) ;
}
int main()
{
Complex c1(1.0,1.0) , c2(2.0,2.0) , c3(4.0,4.0) , c;
double d=0.5 ;
c1.Print();
c=c2+c3 ; c.Print() ;
c+=c1 ; c.Print() ;
c=c+d ; c.Print() ; //可用0.5代替d
c=c3*c2 ; c.Print() ;
c=c3/c1 ; c.Print() ;
cout<<“c3的模为:”<<c3.abs()<<endl ;
c=c3=c2=c1; c.Print(); //连续赋值
c+=c3+=c2+=c1; c.Print(); //连续加赋值
return 0;
}

完成:
1)、如何实现一个整数和一个复数的加法运算(即如:c2=d+c1,其中c1,c2是复数对象,d是一个整数变量)
提示:编写友元函数 friend Complex operator+(int x,Complex &ob);
2)、对示例程序中能够用友元函数实现的运算符,编写友元函数来替换相应的运算符成员函数。
3)、增加重载前置–运算符函数及重载后置–运算符函数,分别用成员函数和友元函数来实现,并测试之。
4)、增加重载的运算符"-"、"-="、"*="、"/=",分别用成员函数和友元函数各做一遍,并测试之。

 Experimental procedure

#include <iostream>
#include <cmath>
using namespace std;
class Complex {
	double	Real, Image;
public:
	Complex(double r = 0.0, double i = 0.0) :Real(r), Image(i) {}
	Complex(const Complex& com)
	{
		Real = com.Real; Image = com.Image;
	}
	void  Print()
	{
		cout << "Real=" << Real << '\t' << "Image=" << Image << '\n';
	}/*
	Complex  operator+(Complex); //重载+运算符函数
	Complex  operator+(double); //重载+运算符函数
	Complex operator+=(Complex); //重载+=运算符函数
	Complex  operator*(Complex); //重载*运算符函数
	Complex  operator/(Complex); //重载/运算符函数
	*/
	Complex operator=(Complex); //重载=运算符函数
	double  abs(void); //求绝对值函数

	friend Complex operator+(const Complex&,const Complex &);//重载+运算符非成员函数
	friend Complex operator+(double, const Complex&);//重载+运算符非成员函数
	friend Complex operator+=(Complex&, const Complex&);//重载+=运算符非成员函数
	friend Complex operator*(const Complex&, const Complex&);	//重载*运算符非成员函数
	friend Complex operator/(const Complex&, const Complex&);	//重载/运算符非成员函数
	friend Complex operator+(int,const Complex&);	/*重载+运算符函数,实现一个整数加一个复数的加法运算*/
	Complex operator--();	//重载前置--运算符成员函数
	friend Complex operator--(Complex&,int);	//重载后置--运算符非成员函数
	
	Complex operator-(const Complex&);	//重载-运算符成员函数
	Complex operator-=(const Complex&);	//重载-=运算符成员函数
	Complex operator*=(const Complex&);	//重载*=运算符成员函数
	Complex operator/=(const Complex&);//重载/=运算符成员函数
	/*
	friend Complex operator-(const Complex&,const Complex&);//重载-运算符非成员函数
	friend Complex operator-=(Complex&,const Complex&);//重载-=运算符非成员函数
	friend Complex operator*=(Complex&,const Complex&);//重载*=运算符非成员函数
	friend Complex operator/=(Complex&,const Complex&);//重载/=运算符非成员函数
	*/
};
Complex operator+(const Complex&c1,const Complex &c2)
{//重载+
	Complex Temp(c1.Real + c2.Real, c1.Image + c2.Image);
	return Temp;
}
Complex operator+(double d,const Complex&c)
{ //重载+ 
	return Complex(c.Real + d, c.Image);
}
Complex Complex::operator=(Complex c)
{//重载=
	Complex temp; //定义temp为可返回Complex类型值,使=可连续使用 
	temp.Real = c.Real;  temp.Image = c.Image;
	Real = temp.Real;  Image = temp.Image;
	return temp;
}
Complex operator+=(Complex &c1,const Complex &c2)
{//重载+ =
	 //为了返回Complex类型的值,使+=可以连续使用 
	c1= c1 + c2;
	return c1;
}
double Complex::abs(void)
{//求绝对值函数
	return sqrt(Real * Real + Image * Image);
}
Complex operator*(const Complex&c1, const Complex&c2)
{//重载*
	return Complex(c1.Real * c2.Real - c1.Image * c2.Image, c1.Real * c2.Image + c2.Real * c1.Image);
}

Complex operator/(const Complex&c1, const Complex&c2)
{ //重载/
	double d = c2.Real * c2.Real + c2.Image * c2.Image;
	return Complex((c1.Real * c2.Real + c1.Image * c2.Image) / d, (c1.Image * c2.Real - c1.Real * c2.Image) / d);
}
//一个整数和一个复数的加法运算
Complex operator+(int m,const Complex&c) 
{
	return Complex(c.Real + m, c.Image);
}
//重载前置--运算符成员函数
Complex Complex::operator--() {
	Complex c;
	Real--; Image--;
	c = *this;
	return c;
}
//重载后置--运算符非成员函数
Complex operator--(Complex&c1, int) {
	Complex c;
	c = c1;
	c1.Real--;
	c1.Image--;
	return c;
}
Complex Complex::operator-(const Complex&c)	//重载后置-运算符成员函数
{
	return Complex(Real - c.Real, Image - c.Image);
}
Complex Complex::operator-=(const Complex&c)//重载-=运算符成员函数
{
	*this =(*this)-c;
	return *this;
}
Complex Complex::operator*=(const Complex&c)//重载*=运算符成员函数
{
	*this = (*this)* c;
	return *this;
}
Complex Complex::operator/=(const Complex&c)//重载/=运算符成员函数
{
	*this = (*this)/c;
	return *this;
}
/*
Complex operator-(const Complex&c1,const Complex&c2)//重载-运算符非成员函数
{
	return Complex(c1.Real-c2.Real,c1.Image-c2.Image);
}
Complex operator-=(Complex&c1,const Complex&c2)//重载-=运算符非成员函数
{
	c1=c1-c2;
	return c1;
}
Complex operator*=(Complex&c1,const Complex&c2)//重载*=运算符非成员函数
{
	c1=c1*c2;
	return c1;
}
Complex operator/=(Complex&c1,const Complex&c2)//重载/=运算符非成员函数
{
	c1=c1/c2;
	return c1;
}
	*/
int main()
{
	Complex c1(1.0, 1.0), c2(2.0, 2.0), c3(4.0, 4.0), c;
	double d = 0.5;
	c1.Print();
	c = c2 + c3;  c.Print();
	c += c1;  c.Print();
	c = c + d; c.Print(); //可用0.5代替d	
	c = c3 * c2;  c.Print();
	c = c3 / c1;   c.Print();
	cout << "c3的模为:" << c3.abs() << endl;
	c = c3 = c2 = c1; c.Print();               //连续赋值
	c += c3 += c2 += c1; c.Print(); //连续加赋值
	//测试重载--运算符
	cout << endl;
	cout << "c:"; c.Print();
	cout << "c1:"; c1.Print();
	c1=--c;
	cout << "c1=--c后\nc:"; c.Print();
	cout << "c1:"; c1.Print();
	c1 = c--;
	cout << "c1=c--后\nc1:"; c1.Print();
	cout << "c: "; c.Print();
	//测试-、-=、*=、/=重载运算符;
	cout << "c-c1: "; (c - c1).Print();
	c -= c1;
	cout << "c-=c1后\nc:"; c.Print();
	c *= c1;
	cout << "c*=c1后\nc:"; c.Print();
	c /= c1;
	cout << "c/=c1后\nc:"; c.Print();
	return 0;
}

 Experimental results and analysis

在这里插入图片描述

The operation results meet the expectations

 Experimental process analysis

We know a C + + class. If the programmer does not define the overloaded function of assignment operator for it, the compiler will implicitly define it, so if we define the overloaded function of global assignment operator again, ambiguity will occur. Even if the compiler allows such a definition technique, it cannot compile at the time of calling.
我们知道一个c++类,程序员如果没有为其定义了赋值操作符重载函数,编译器也会隐式的定义,这样倘若再定义全局赋值运算符重载函数,将会发生二义性。即使编译器允许这样的定义手法,在调用的时候也编译不过。
在这里插入图片描述
The assignment (=), subscript ([]), call (()), and member access arrow (- > operators must be members (functions).
赋值(=)、下标([])、调用(())和成员访问箭头(->)运算符必须是成员(函数)。
Secondly, in the process of debugging, I found that when overloading composite operators, we can use operators that have been overloaded to simplify the code. For example, the assignment operator of two objects, the operator of adding and subtracting between two objects, etc.
其次,在调试过程中我发现:当重载复合运算符的过程中,可以利用已经重载好的运算符来达到简化代码的目的。例如两个对象的赋值运算符,两个对象之间相加减的运算符等。
在这里插入图片描述
In the function of overloading the - = operator in the picture, the code is simplified only by using the - which operates between two objects already overloaded.
图片中重载-=运算符的函数中,只用利用已经重载好的两个对象之间进行操作的-来简化代码。

 Empirical conclusioin

The assignment (=), subscript ([]), call (()), and member access arrow (- > operators must be members (functions).
赋值(=)、下标([])、调用(())和成员访问箭头(->)运算符必须是成员(函数)。
Note: non member versions of overloaded operator functions require the same number of parameters as the number of operands used by operators; member versions require one less parameter because one of the operands is the calling object that is implicitly passed.
注意:非成员版本的重载运算符函数所需的形参数目与运算符使用的操作数数目相同;而成员版本所需的参数数目少一个,因为其中的一个操作数是被隐式地传递的调用对象。

T3.Experiment summary

For the member function version, one operand is implicitly passed through this pointer, and the other operand is explicitly passed as a function parameter; for the friend version, both operands are passed as parameters.
对于成员函数版本来说,一个操作数通过this指针隐式地传递,另一个操作数作为函数参数显式地传递;对于友元版本来说,两个操作数都作为参数传递。
Remember that when you define an operator, you must select one of the formats, not both. Because these two formats match in the same expression, defining these two formats at the same time will be regarded as ambiguous errors, resulting in compilation errors.
So which format is the best? For some operators, as mentioned earlier, member functions are the only legitimate choice. In other cases, there is not much difference between the two formats. Sometimes, depending on the class design, it may be better to use the nonmember function version (especially when defining a type conversion for a class)
记住,在定义运算符时,必须选择其中的一个格式,而不能同时选择这两种格式。因为这两种格式于同一个表达式匹配,同时定义这两种格式将被视为二义性错误,导致编译错误。
那么哪种格式最好呢?对于某些运算符来说(如前所述),成员函数是唯一合法的选择。在其他情况下这两种格式没有太多区别。有时,根据类设计,使用非成员函数版本可能更好(尤其是为类定义类型转换时)

By Suki
2020/5/2
做实验作业是一个很好的记忆C++知识点的方法,在做的过程中,不断地思考代码的简洁性(同时保证可读性),并且可以自己高自由度的不断尝试不一样的方法,不断调试代码,有疑问的地方先去网上查资料,其次才是询问老师或者学长,最后再自己思考总结。这就是成长的过程,忙碌却又不失条理。不断向前那就是正在进步着。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
运算符重载C++中的一种特性,它允许我们对已有的运算进行重新定义,以便适应自定义型的操作。通过运算符重载,我们可以为自定义添加与其他对象的相加、相减、相乘等操作。 下面是运算符重载的定义和示例代码: 定义: 1. 运算符重载使用特殊的函数名和语法来定义。函数名以`operator`关键字开始,后面跟着要重载运算。 2. 运算符重载函数可以作为的成员函数或全局函数进行定义。 3. 运算符重载函数必须指定参数和返回型,以及如何执行相应的操作。 示例代码: ```cpp class MyNumber { private: int value; public: MyNumber(int num) : value(num) {} // 运算+的重载 MyNumber operator+(const MyNumber& other) { int result = this->value + other.value; return MyNumber(result); } // 运算<<的重载(全局函数) friend std::ostream& operator<<(std::ostream& os, const MyNumber& obj); }; // 运算<<的重载(全局函数) std::ostream& operator<<(std::ostream& os, const MyNumber& obj) { os << obj.value; return os; } ``` 使用运算符重载的示例代码: ```cpp MyNumber num1(5); MyNumber num2(10); MyNumber sum = num1 + num2; // 使用重载的+运算进行相加操作 std::cout << "Sum: " << sum << std::endl; // 使用重载的<<运算进行输出操作 ``` 在上述示例中,我们定义了一个名为`MyNumber`的,并重载运算`+`和`<<`。重载的`+`运算用于对两个`MyNumber`对象进行相加操作,返回一个新的`MyNumber`对象。重载的`<<`运算用于在输出流中输出`MyNumber`对象的值。 需要注意的是,不是所有的运算都可以被重载,例如赋值运算`=、`.`和`::`等不能被重载。此外,运算符重载也需要遵循一些约定和限制,例如保持运算的原有语义,避免过度使用运算符重载等。 运算符重载C++中强大且灵活的特性,可以使我们的代码更加直观和易读。但在使用时需要慎重考虑,并确保合语义和预期行为。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值