c++面向对象第十章运算符重载(1)
C++基础系列——运算符重载

C++基础系列——运算符重载1. 运算符重载简介所谓重载,就是赋予新的含义。
函数重载(Function Overloading)可以让⼀个函数名有多种功能,在不同情况下进⾏不同的操作。
同样运算符重载(Operator Overloading)可以让同⼀个运算符可以有不同的功能。
可以对 int、float、string 等不同类型数据进⾏操作<< 既是位移运算符,⼜可以配合 cout 向控制台输出数据也可以⾃定义运算符重载:class Complex{public:Complex();Complex(double real, double imag);Complex operator+(const Complex &a) const;void display() const;private:double m_real;double m_imag;};// ...// 实现运算符重载Complex Complex::operator+(const Complex &A) const{Complex B;B.m_real = this->m_real + A.m_real;B.m_imag = this -> m_imag + A.m_imag;return B;// return Complex(this->m_real + A.m_real, this->m_imag + A.m_imag);}int main(){Complex c1(4.3, 5.8);Complex c2(2.7, 3.7);Complex c3;c3 = c1 + c2; // 运算符重载c3.display();return 0;}运算结果7 + 9.5i运算符重载其实就是定义⼀个函数,在函数体内实现想要的功能,当⽤到该运算符时,编译器会⾃动调⽤这个函数,它本质上是函数重载。
运算符重载(面向对象程序设计C++)

运算符重载运算符重载的本质是函数重载,它也是C++多态的一种体现,为用户提供了一个直观的接口,调用运算符操作自定义数据类型其实就是调用运算符函数。
运算符重载增强了C++的可扩充性,使得C++代码更加直观、易读,且便于对对象进行各种运算操作。
重载的运算符是具有特殊名字的函数:它们的名字由关键字operator 和其后要重载的运算符共同组成。
语法格式 返回类型 operator 运算符(参数列表){函数体; }运算符重载规则:只能重载C++中已有的运算符,不能创建新的运算符。
重载之后的运算符不能改变其优先级和结合性,也不能改变其操作数的个数及语法结构。
避免没有目的地使用重载运算符。
类属关系运算符“.”、成员指针运算符“*”、作用域运算符“::”、sizeof 运算符和三目运算符“?:”不可以重载。
输入输出运算符的重载 IO 标准库使用“>>”和“<<”运算符执行输入输出操作,对于这两个运算符来说,IO 库定义了其基本数据类型的操作,但若要直接对类对象进行输入输出,则需要在类中重载这两个运算符。
输入运算符语法格式istream& operator>>(istream&, 类对象引用);输出运算符语法格式ostream& operator<<(ostream&,const 类对象引用); 关系运算符的设计准则关系运算符都要成对的重载。
“==”运算符应该具有传递性当成对出现运算符重载时,可以把一个运算符的工作委托给另一个运算符。
赋值运算符的重载对于赋值运算符来说,如果不重载,那么类会自动为我们提供一个赋值运算符。
这个默认的赋值运算符跟默认拷贝构造函数一样,就是把一个对象的数据成员的值复制给另一个对象对应的数据成员。
下标运算符的重载返回类型 operator[] (参数列表);重载“[]”运算符可以实现两个目的:(1)“对象[下标]”的形式类似于“数组[下标]”,更加符合习惯。
重载的概念(精)

重载
} vector vector::operator -( vector v1) {
vector v;
v.x = - v1.x; v.y = - v1.y;
return v;
} void main() { vector v1(4.5,-7.8),v2(-1.5,1.2);
v1.print();
重载
Increase & operator ++(); Increase operator ++(int); void display() {cout <<"the value is"<<value<<endl;} //前缀方式
重载
protected:
int value; }; Increase & Increase::operator ++() {
重载
例1 求绝对值函数abs()的重载。 int abs(int x) {
return(x>=0?x:-x);
} float abs(float x) { return(x>=0?x:-x); } long abs(long x)
{
重载
return(x>=0?x:-x);
} double abs(double x) { return(x>=0?x:-x);
v2.print();
重载
}
运行结果为: 4.5 -7.8 -1.5 1.2 3 -3 -6.6 6.6
重载运算符在调用时仍然是靠参数区分的。上例中 重载的运算符“-”,若出现在两个数据之间,只要这两 个数据为相同的基本数据类型、vector类型或其它重载 过的类型,都能正确调用相应的运算代码;若它单独出 现在某个基本数据类型或vector类型等重载过的数据前 面,则自动执行求“相反数”的运算。
C_运算符重载_各类详细介绍

▪ 说明
运算符重载函数 operator@()可以返回任何类型,甚至可 以是 void类型,但通常返回类型与它所操作的类的类型 相同,这样可使重载运算符用在复杂的表达式中。例如, 在例7-2中,可以将几个复数连续进行加、减、乘、除的 运算。
用友元函数重载单目运算符时,需要一个显式的操作数, 例7-3中,用友元函数重载单目运算符“-”
#include<iostream.h> class nclass{ int a,b; public:
nclass(int x=0,int y=0) { a=x;b=y;} friend nclass operator -(nclass obj); void show(); };
▪ complex operator+(complex com1,complex com2) { return complex(com1.real+com2.real,com1.imag+com2.imag;}
▪ 这种方法是直接将一个无名临时对象创建到主调函数中,那么 运行效率高于前一种。
▪ 单目运算符重载
nclass operator-(nclass obj) { obj.a=-obj.a;
obj.b=-obj.b; return obj;} void nclass::show() { cout<<"a="<<a<<" b"<<b;} ▪ main() ▪{ ▪ nclass ob1(10,20),ob2; ▪ ob1.show(); ▪ ob2=-ob1; ▪ ob2.show(); ▪ return 0; ▪}
运算符重载

{
rpart=rp;
ipart=ip;
}
Complex add( const Complex & com )
{
Complex temp ;
temp .rpart= com .rpart+rpart;
temp .ipart= com .ip+ipart;
return temp ;
}
2020/7/2
பைடு நூலகம்};
★单目运算符重载 :
Complex Complex:: operator {
Complex temp;
( 单) 目无参数 双目一个参数
temp.rpart=-rpart;
temp.ipart)=-ipart;
return temp;
}
Complex c=-a+b;
(a.operator-( )).operator+(b)
};
point point::operator+ (point p1)
{ point p; p.x=x+p1.x; p.y=y+p1.y; return p; }
void main()
{ point p1(10,10),p2(20,20); p1=p1+p2 ;
p1.print(); ++p1; p1.print();
}
//(╳)
运算符成员函数——调用成员函数的对象隐式成为表达式的第一个运算数 外部运算符函数——其第一个参数直接对应表达式的第一个运算数;
x1=x2+x3;
operator+(x2, x3);
2020/7/2
6 6
简述运算符重载的规则。

简述运算符重载的规则。
篇一:运算符重载是C/C++语言中一种强大的功能,允许程序员自定义函数的行为,以处理不同类型的数据。
运算符重载允许程序员在函数中重载算术、逻辑和位运算符,从而能够处理数组、结构体和指针等不同类型的数据。
以下是运算符重载的规则:1. 算术运算符重载算术运算符包括加号、减号、乘号和除号。
每个算术运算符都有一组默认的行为,可以通过运算符重载来自定义它们的行为。
例如,重载加号运算符可以使函数接受一个整数参数,并返回一个新的整数。
下面是一个简单的例子,演示了如何重载加号运算符:```c++struct MyStruct {int value;};MyStruct operator+(const MyStruct& other, int value) {return MyStruct(value + other.value);}int main() {MyStruct mystruct1 = { 10 };MyStruct mystruct2 = { 20 };int result = mystruct1 + mystruct2;std::cout << "result = " << result << std::endl;return 0;}```在上面的例子中,我们定义了一个名为`MyStruct`的结构体类型,其中包含一个整数类型。
然后,我们定义了一个重载加号运算符的函数,该函数接受一个整数类型的参数,并返回一个新的`MyStruct`对象。
在`main`函数中,我们定义了两个`MyStruct`对象`mystruct1`和`mystruct2`,并将它们相加,结果存储在`result`变量中。
2. 逻辑运算符重载逻辑运算符包括条件运算符和逻辑非运算符。
每个逻辑运算符都有一组默认的行为,可以通过运算符重载来自定义它们的行为。
第十章 运算符重载

7.赋值运算符
只要是用户定义的类或结构,都应能进行赋值运算,如: Struct S{int a,b; }; S a,b; a=b; //c语言允许如此赋值 对任何类,像拷贝构造函数一样,c++也默认提供赋值运算符,但要区别拷 贝构造函数和赋值运算符: void fn(MyClass& mc) { MyClass newMC=mc; //这是拷贝构造函数 newMC=mc; //这是赋值运算符 } 在拷贝构造函数中,我们碰到深拷贝与浅拷贝的问题,赋值运算符也同样, 什么时候浅拷贝不合适,就应提供赋值运算符。 通常赋值运算符有两部分,第一部分与析构函数类似,在其中取消对象已经 占用的资源。第二部分与拷贝构造函数类似,在其中分配新的资源。
6.转换运算符
转换运算符的声明形式为: operator 类型名( ); 它没有返回类型,因为类型名就代表了它的返回类型。 转换运算符将对象转换成类型名规定的类型。转换时的形式就象强不行的,因为强制转换只 能对基本数据类型进行操作,对类类型的操作是没有定义的。 要防止同一类型提供多个转换路径,它会导致编译出错,例如: class A { void main() { public: B sb; A(B& b); //用B构造A A a=A(sb); //是构造还是转换? //… } }; class B { public: operator A(); //B转换成A //… };
C++规定,运算符中,参数说明都是内部类型时,不能重载。例如不允许声 明: int * operator + (int, int*); 即不允许进行下述运算: int a=5; int *pa=&a; pa=a*pa; //error C++基本数据类型之间的关系是确定的,如果允许定义其上的新操作,那么, 基本数据类型的内在关系将混乱。 C++还规定了“. :: .* .-> ?:”这5个运算符不能重载,也不能创造新运算 符。例如,不允许声明: int operator @(int,int); 或者: int operator :: (int,int);
C 期末考试第十章运算符的重载复习提纲完整ppt

定义作为友元函数的重载函数 {
赋值 pt.x++; _____运算_______________
return pt; } int main() { int m; while(cin>>m) { Point p1(m,m),p2(m+1,m+1),p3; (++p1).print(); p3 = p2++; p3.print(); p2.print(); } return 0; }
Complex(){real=0;imag=0}
//定义构造函数
Complex(double r,double i){real=r; imag=I;} //构造重载函数
Complex operator + (Complex &c2)
//声明重载运算符的“+”函数
void display();
//定义输出函数
*4、::重C载sizo不emo能f p改?:l变ex运算C符o对m象p的le个x数::operator +(Complex &c2) //定义重载运算符“+”的函数
class {Complex
* :: sizeof ?: {
Complex c;
赋值
c.real=real+c2.real;
pt. void
二、重载的方法:
运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符 时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过 定义函数实现的。运算符重载实质上是函数的重载。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
★ 归纳 ◆ 函数operator+重载了运算符+ ◆ 在执行复数相加的表达式c1+c2时,系统就会调用 operator+函数,把c1和c2作为实参,与形参进行 虚实结合
二、 运算符重载的方法
1、 典例分析
★
例10.2:改写例10.1,重载运算符“+”,
使之能用于复数的相加
#include <iostream>
可以将运算符重载函数作为成员函数,如下面
的形式 ◆ Complex Complex::operator + (int &i) { return Complex(real+i;image);}
★ 注意:在表达式中重载的运算符“+”左侧应为
Complex类的对象,如:
◆ c3=c2+i; ◆ 不能写成:c3=i+c2; // 运算符的左侧不是类对象,编译出错
cout<<“c1+c2=”;c3.display();
return 0;}
★ 问题:“+”是双目运算符,为什么该重载函数只 有 一个参数呢? ◆ 实际上,该运算符重载函数有两个参数
◆ 由于重载函数是Complex类中的成员函数,有一
个参数是隐含的,运算符函数用this指针隐式地
访问类对象的成员
★ 详细分析 ◆ 在将运算符函数重载为成员函数后,如果出现含 该运算符的表达式,如c1+c2,编译系统把它解释 为c1.operator+(c2) ◆ 即通过对象c1调用运算符重载函数,并以表达式 中的第二个参数作为函数实参
◆
将运算符“+”重载为适用于复数加法,
但重载函数不作为成员函数,而是放在
类外,作为Complex的友元函数
#include <iostream>
using namespace std;
class Complex
{ public: Complex(){ real=0,image=0 }; Complex(double r,double i) { real=r,image=i}; // 构造函数的重载
void display();
protected:
double real; // 实部
double image;
};
// 虚部
Complex Complex::operator +(Complex &c2) { Complex c; c.real=real+c2.real; c.image=image+c2.image;
4、 重载既不能改变运算符的优先级别, 也不能改变运算符的结合性 ★ ★ 优先级别:比如先乘除、后加减 结合性:如赋值运算符是右结合性
第四节 运算符重载函数作为 类成员函数和友元函数
一、 运算符重载函数作为类成员函数
★
典例分析:例10.2
二、 运算符重载函数可以是非成员 函数
★ 典例分析:例10.3
2、 C++允许重载的运算符
★
C++绝大部分的运算符允许重载,
不能重载运算符只有5个(P319)
第三节 运算符重载的规则
3、 重载不能改变运算符运算对象(即操作 对象)的个数 ★ ★ 概念:双目运算符和单目运算符 双目运算符在重载以后仍为双目运算符 (如关系运算符>和<)
第三节 运算符重载的规则
2、 问题:用户能否根据自己的需要对C++ 已提供的运算符进行重载? ★ ★ 比如:能否用“+”实现两个复数的相加 典例10.1(未使用运算符重载)
#include <iostream>
using namespace std;
class Complex
{ public: Complex(){ real=0,image=0 }; Complex(double r,double i) { real=r,image=i }; // 构造函数的重载 Complex complex_add(Complex &c2); void display();
//定义三个复数对象
c3=c1+c2; // 运算符+用于复数运算 c1.display(); c2.display();
cout<<“c1=”; cout<<“c2=”;
cout<<“c1+c2=”;c3.display();
return 0;}
★ 在将运算符函数重载为非成员函数后,C++编译
系统将程序中的表达式c1+c2解释为:
(Complex &c1,Complex &c2)
{ return Complex(c1.real+c2.real;
c1.image+c2.image);} void Complex::display() { ...... }
int main()
{ Complex c1(3,4),c2(5,-10),c3;
using namespace sБайду номын сангаасd;
class Complex
{ public: Complex(){ real=0,image=0 }; Complex(double r,double i) { real=r,image=I }; // 构造函数的重载 Complex operator +(Complex &c2); // 声明重载运算符的“+”函数
return 0;}
二、运算符的重载
3、 归纳
★ ★
结果无疑是正确的 但调用方式很不直观,太繁琐,使人
感到不方便
第二节 运算符重载的方法
一、 运算符重载的定义
1、 运算符重载是通过定义函数实现的 ★ 在需要执行被重载的运算符时,系统就
自动调用该函数(运算符重载的实质是 函数的重载)
一、 运算符重载的定义
1、 运算符也可以重载
★
实际上,我们已经在不知不觉中使用了
运算符的重载
★ 例如:大家都已习惯于用加法运算符“+”对整数、
单精度数和双精度数进行加法运算
如:5+8、5.8+3.7等等 ◆ 其实计算机对整数、单精度数和双精度数的加法 过程很不相同 ◆ 原因:C++已经对运算符“+”进行了重载
二、运算符的重载
operator+(c1,c2) ◆ 即执行c1+c2相当于调用以下函数: Complex operator + (Complex &c1,Complex &c2) { return Complex(c1.real+c2.real;
c1.image+c2.image);}
三、 归纳
1、 运算符重载函数可以是类的成员函数, 也可以是类的友元函数,还可以是既
friend Complex operator +
(Complex &c1,Complex &c2);
// 重载函数为友元函数
void display(); protected: double real; double image; }; // 实部 // 虚部
Complex Complex::operator +
return c;}
Void complex::display()
int main()
{ Complex c1(3,4),c2(5,-10),c3;
//定义三个复数对象
c3=c1+c2; // 运算符+用于复数运算 c1.display(); c2.display();
cout<<“c1=”; cout<<“c2=”;
2、 运算符重载的一般格式
★
函数类型 operator 运算符名称
(形参表列)
{ 对运算符的重载处理}
★ 典例:想将“+”用于Complex类(复数)的加法
运算,函数的原型可以是这样的:
◆ Complex operator +(Complex c1, Complex c2); ◆ 注意:函数名是由关键字operator和运算符组成
二、 运算符重载的方法
2、 归纳
★
通过运算符重载,扩大了C++已有运算
符的作用范围,使之能用于类对象
★
使C++具有更强大的功能,更好的可扩 充性和适应性
第三节 运算符重载的规则
1、 C++不允许用户自己定义新的运算符, 只能够对已有的C++运算符进行重载 ★ 例如:不能将**定义为幂运算符
第三节 运算符重载的规则
int main()
{ Complex c1(3,4),c2(5,-10),c3;
//定义三个复数对象
c3=plex_add(c2); //调用复数相加函数 cout<<“c1=”; cout<<“c2=”; c1.display(); c2.display();
cout<<“c1+c2=”;c3.display();
非类的成员函数也不是类的友元函数
的普通函数 ★ 后者问题在于:不能访问类的私有成员
三、 归纳
2、 如果将运算符重载函数作为成员函数, 它可以通过 this指针自由地访问本类的
数据成员,因此,可以少写一个函数的
参数 ★ 但要求运算表达式的第一个参数是一个 类对象,而且与运算符函数的类型相同
★ 例如:欲将一个复数和一个整数相加,如c1+i,