第11章77 运算符重载

合集下载

11章运算符重载

11章运算符重载

考虑用普通函数实现两个复数相加
Complex complex_add(Complex &c1, Complex &c2) { Complex c; c.real=c1.real+c2.real; c.imag=c1.imag+c2.imag; return c; }
将其声明为Complex 类的友元函数
int operator + (int a, int b) {return (a-b);}
(8)用于类对象的运算符一般必须重载,但有两个例外,运算 符“=”和“&”不必用户重载。 ① 赋值运算符(=)可以用于每一个类对象,可以利用它在 同类对象之间相互赋值(系统已经为每一个新声明的类重载 了一个赋值运算符,他的作用是逐个复制类的数据成员)。 ② 地址运算符&也不必重载,它能返回类对象在内存中 的起始地址。 (9)应当使重载运算符的功能类似于该运算符作用于标准类型 数据时所实现的功能。 (10)运算符重载函数可以是类的成员函数,也可以是类的友 元函数,还可以是既非类的成员函数也不是友元函数的普通 函数。
后自增
在自增(自减)运算符重载函数中,增加一个int型形参,就是后置自 增(自减)运算符函数。
#include <iostream> Complex Complex::operator ++ (int) using namespace std; { //对象复制,保存修改前对象状态 class Complex Complex temp(*this); {public: real++; imag++; //对象自增 Complex( ) return temp; //返回的是自加前的对象 {real=0; imag=0;} } Complex(double r,double i) {real=r; imag=i;} void Complex∷display( ) //重载后自增++函数 cout<<″(″<<real<<″,″<<imag<<″i) Complex operator + { +(int); void display( ); ″<<endl;} private: int main( ) double real; { Complex c1(3,4),c2; double imag; c2=c1++; // c1. operator ++ (0) }; cout<<″c1=″; c1.display( ); cout<<″c2=″; c2.display( ); }

C++基础系列——运算符重载

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运算符重载其实就是定义⼀个函数,在函数体内实现想要的功能,当⽤到该运算符时,编译器会⾃动调⽤这个函数,它本质上是函数重载。

第11章 运算符重载

第11章 运算符重载

• 这并不会引起任何编译错误,但将引起逻辑上的混乱。 因此,重载一个运算符时,其具体操作还应尽量与该 运算符的原始含义保持一致。
重载一元运算符为类运算符
• 由于类运算符的第一操作数约定为当前对象(隐含),所 以用成员函数实现一元运算符重载的格式为: type ClassName::operator 单目运算符( ) { … } //函数体 • “++”和“--”运算符的重载方法相似,但有前置和后置 之分,应在定义运算符重载函数时有所区分。 • 以“++”运算符的重载为例说明其实现的方法: type ClassName::operator++( ) //前置 { … } type ClassName::operator++(int)//后置 { … } • 仅有形式意义,无需再写形参名。
重载运算符为友元运算符
• 友元运算符:某运算符重载函数被定义为类的友元。 • 注意:友元没有this指针,因此,参与运算的操作数 都必须在运算符重载函数的参数表中明确说明。 • 类X的一元友元运算符的定义格式: type operator@(参数说明) { … }
• 参数为左操作数,是类X的对象或引用。 ++、--运算符:参数只能是类X的引用 +、-运算符:参数为类X的引用或对象
重载二元运算符为类运算符
• 若某运算符重载函数被定义为类的成员,则称该运算 符为该类的运算符,简称类运算符。 • 由于类运算符的第一操作数约定为当前对象(隐含),所 以定义二元类运算符重载函数的一般格式为: type ClassName::operator @ (Arg) { … } //函数体 type:函数返回值类型 ClassName:运算符重载函数所在的类名 operator:关键字,与其后的运算符一起构成函数 名,有区别于其他函数名。 @:一个重载的二元运算符 Arg:函数的形参表,即第二操作数。

C_运算符重载_各类详细介绍

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; ▪}

第11章运算符重载

第11章运算符重载

运算符重载函数是类成员函数
一元运算符 @表示要重载的运算符 表示要重载的运算符 隐式调用: 对象名 对象名@ 隐式调用:@对象名 或者 对象名 显示调用:对象.operator@( ) 显示调用:对象 二元运算符 隐式调用:对象名 对象名2 隐式调用:对象名1@对象名 对象名 显示调用:对象名1.operator@(对象名 对象名2) 显示调用:对象名 对象名
例如:下边是运算符重载的另一个例子,程序实现了复数的加 例如:下边是运算符重载的另一个例子, 和减运算。(二元操作符) 。(二元操作符 和减运算。(二元操作符)
#include <iostream> using namespace std; class Complex { public: Complex() { real=0.0;imag=0.0; } Complex(double r) { real=r; imag=0.0; } Complex(double r,double i) { real=r; imag=i; } Complex operator+(const Complex& c); Complex operator-(const Complex& c); friend void print(const Complex& c); private: double real,imag; };
运算符重载为友元函数形式
注意: 注意:友元函数重载运算符调用方式 @表示要重载的运算符 表示要重载的运算符 二元运算符 显示: 对象名1,对象名 显示:operator@(对象名 对象名 对象名 对象名2) 隐式:对象名1@对象名 对象名2 隐式:对象名 对象名 一元运算符 显示: 对象名) 显示:operator@(对象名 对象名 隐式: 对象名 对象名@ 隐式:@对象名 或者 对象名

第11章 运算符重载

第11章 运算符重载
15
► 1.
双目运算符重载为类的友元函数,形式如下:
所属类型 &obj1)
返回类型 operator op(const 所属类型 &obj1,const { …… // obj1和obj2分别对应两个运算对象 }
“obj1 op obj2” ► 相当于operator op(obj1,obj2)
► 经过重载后,表达式
17
15complex operator +(const complex &c1,const complex &c2) 16{ complex c3; 17 c3.real=c1.real+c2.real; 18 c3.imag=c1.imag+c2.imag; 19 return c3; 20 } 21complex operator -(const complex &c1,const complex &c2) 22{ complex c3; 23 c3.real=c1.real-c2.real; 24 c3.imag=c1.imag-c2.imag; 25 return c3; 26 } 27 int main() 28 { complex c1(1,2),c2(3,4),c3; 29 30 //输出4+6i c3=c2+c1; c3.display(); 31 c3=c2-c1; c3.display(); //输出2+2i return 0; 32 }
5
► 1.
双目运算符重载为类的成员函数,形式如下: 返回类型 类名::operator op(const 所属类型 { …… //this指针对应obj1运算对象 }
&obj2)

重载运算符语法讲解

重载运算符语法讲解

重载运算符语法讲解重载运算符这篇随笔我来讲解⼀下C++语⾔中重载运算符的相关知识。

⼀、重载运算符的⽤途这是⼀个⽐较哲学的问题:我们为什么要重载运算符?理由就是,我们C++语⾔中已经给出的运算符(包括算数运算符和逻辑运算符)只是针对C++语⾔中已经给定的数据类型进⾏运算,假如我们想要对我们的⾃定义数据类型进⾏运算的话,则需要重载运算符,我们可以把重载运算符理解成对已有的运算符的⼀种重新定义。

⽐如:double a,b,c;a=1/3;b=1/2;c=a+b;printf("%lf",c);这段程序输出的肯定不是两个分数相加的结果。

这时候我们就可以重载运算符+。

⼆、重载运算符的实现语法格式如下(⾮常重要)<返回类型> operator <运算符符号>(<参数>){<定义>;}这⾥我们举⼀个例⼦。

在优先队列(priority_queue)中,存储的元素较⼤的会被放到堆顶。

如果存的是int或者string等类型还好办(因为他们本⾝就可以互相⽐较⼤⼩),如果是我们⾃定义的结构体类型,那就需要重载<运算符。

⽐如:struct node{int id;double x,y;}//定义结构体bool operator <(const node &a,const node &b){return a.x<b.x && a.y<b.y;}//重载运算符“<”注:这⾥的结构体保存了⼀个整型变量id,两个长浮点变量x,y,表⽰坐标。

这⾥的重载运算符先⽐横坐标后⽐纵坐标。

三、重载运算符的注意事项。

以下运算符不可重载:关系运算符"."成员指针运算符".*"作⽤域运算符"::"sizeof运算符三⽬运算符"?:"重载运算符限制在C++语⾔中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符。

结构体重载运算符

结构体重载运算符

结构体重载运算符
运算符重载是指在C++程序设计语言中,可以为现存的类型定义新的运算符的
功能。

运算符重载也就是给C++中的某些运算符功能上增加定义和改变其内部操作
以适应业务程序需求、提高程序开发效率而实现的技术。

运算符重载对于改善C++程序设计语言的结构表达和可读性都有着重要的作用。

它使得在C++程序设计过程中,可以利用运算符重载将复杂的算法编写简洁,更容
易理解,并且更有利于程序可维护性和可维护性。

一般来说,重载的运算符必须是类的成员函数,而且也不能对运算符的优先级
有改变,而改变其函数原型。

当某个运算符被重载时,它可以按照开发者的要求来处理数据。

例如,可能需要定义一个加法运算符“+”,但是此加法运算符可以处
理不同类型或参数的数据,以便在实际开发过程中更方便。

此外,要使用运算符重载,还需要遵循限制使用运算符的规则,例如,要使用
类中的成员函数定义运算符,且不能重载任何C++系统或类型操作符,因此必须时
刻注意自己的操作,以免搞砸整个运算符重载,对程序编写带来干扰。

总之,运算符重载的主要用途在于改善C++程序编写的优雅性和简洁性,以及
提高开发者使用程序设计语言的效率。

像一些复杂的运算符一样,重载运算符可以帮助程序员实现更有效、更简洁的算法,因此可以将难以理解和记忆的复杂混乱的算法变成一句简单的话。

运算符重载

运算符重载
CCS E
24
运算符重载
思考:如果希望表达式i+c1有意义, 思考:如果希望表达式i+c1有意义,应该 i+c1有意义 如何定义重载运算符函数? 如何定义重载运算符函数?
friend Complex operator+(int &i,Complex &c); Complex operator+(int &i, Complex &c) {return Complex(i+c.real,c.imag);}
2
什么是运算符重载
代码分析: 代码分析: 例10.1 通过函数来实现复数 相加。 相加。
CCS E
3
运算符重载的方法
运算符重载的方法是定义一个重载运 算符的函数, 算符的函数,在需要执行被重载的运 算符时,系统就自动调用该函数, 算符时,系统就自动调用该函数,以 实现相应的运算。也就是说, 实现相应的运算。也就是说,运算符 重载是通过定义函数实现的。 重载是通过定义函数实现的。运算符 重载实质上是函数的重载。 重载实质上是函数的重载。
CCS E
21
运算符重载
如果将运算符重载函数作为成员函数, 如果将运算符重载函数作为成员函数, 它可以通过this this指针自由地访问本类 它可以通过this指针自由地访问本类 的数据成员, 的数据成员,因此可以少写一个函数 的参数。 的参数。但必须要求运算表达式第一 个参数(即运算符左侧的操作数) 个参数(即运算符左侧的操作数)是一 个类对象, 个类对象,而且与运算符函数的类型 相同。 相同。因为必须通过类的对象去调用 该类的成员函数,而且只有运算符重 该类的成员函数, 载函数返回值与该对象同类型, 载函数返回值与该对象同类型,运算 结果才有意义。 结果才有意义。

简述运算符重载的规则。

简述运算符重载的规则。

简述运算符重载的规则。

篇一:运算符重载是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. 逻辑运算符重载逻辑运算符包括条件运算符和逻辑非运算符。

每个逻辑运算符都有一组默认的行为,可以通过运算符重载来自定义它们的行为。

运算符重载

运算符重载

运算符重载为类的友元函数
类中的声明: 类中的声明: friend 函数类型 operator 运算符(参数表); 运算符(参数表); 运算符重载函数的定义形式: 运算符重载函数的定义形式: 运算符(参数表) 函数类型 operator 运算符(参数表) { 函数体; 函数体; } 附加例) (附加例)用友元函数实现复数的加法运算符的重 载。
数据类型转换 标准数据类型转换
隐式转换: 自动转成double型) 隐式转换:7.5+2 (将2自动转成 将 自动转成 型 显式转换: 转成整型) 显式转换:int(89.5) (将89.5转成整型 将 转成型
涉及到类类型的转换
对于用户自己声明的类型, 对于用户自己声明的类型,编译系统并不知道怎样进行转 换。解决这个问题的关键是让编译系统知道怎样去进行转 换,需要定义专门的处理函数。 需要定义专门的处理函数。 将一个其他类型的数据转换成一个类类型: 将一个其他类型的数据转换成一个类类型:转换构造函数 将一个类的对象转换成另一类型的数据: 将一个类的对象转换成另一类型的数据:类型转换函数
运算符重载的格式
运算符重载为类的成员函数 运算符重载为类的友元函数
运算符重载的规则

② ③ ④ ⑤
.”、 *” ::”、 ?:”和 sizeof”等几个运 除“. 、“*”、“:: 、“?: 和“sizeof 等几个运 算符不能重载外, 算符不能重载外,C++中几乎所有的运算符都可以 中几乎所有的运算符都可以 重载。 重载。 运算符被重载后,其优先级和结合性不会改变。 运算符被重载后,其优先级和结合性不会改变。 不能改变运算符操作对象的个数。 不能改变运算符操作对象的个数。 运算符的意义应不变。 运算符的意义应不变。 用于类对象的运算符一般必须重载,但有两个例外, 用于类对象的运算符一般必须重载,但有两个例外, 运算符“ 和 不必用户重载。 运算符“=”和“&”不必用户重载。 不必用户重载

第11章77 运算符重载

第11章77 运算符重载

bool operator<=(const Rational &r1) const;
bool operator>=(const Rational &r1) const;
bool operator!=(const Rational &r1) const;
void display() { cout << num << '/' << den; }
5
不能重载的运算符
. .* :: ?: sizeof
第11章77 运算符重载
6
第11章 运算符重载
什么是运算符重载 运算符重载的方法 几个特殊的运算符的重载 自定义类型转换运算符 运算符重载实例
第11章77 运算符重载
7
运算符重载的方法
运算符重载就是写一个函数解释某个运算符在 某个类中的含义
运算符的重载不能改变运算符的运算对象数。因此,重载函 数的形式参数个数(包括成员函数的隐式指针this)与运算 符的运算对象数相同
运算符重载可以重载成成员函数也可以重载成全局函数实现。 重载成全局函数时,最好把此函数设为友员函数
如果作为类的成员函数,它的形式参数个数比运算符的运算 对象数少1。这是因为成员函数有一个隐含的参数this。在 C++中,把隐含参数this作为运算符的第一个参数。
第11章77 运算符重载
4
可以重载的运算符
+ - * / % ^ &| ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- ->* , -> [] () new delete new[] delete[]

运算符重载——精选推荐

运算符重载——精选推荐

运算符重载运算符重载学习运算符重载,让运算符能做⼀些原来做不了的事情,⽅便它的使⽤⼀、运算符重载的概念1、什么是运算符重载1.重载:重新载⼊,就像之前学的函数重载,对⼀个已有的函数赋值⼀个新的定义,因此同⼀个函数名就可以有不同的含义。

2.运算符也是可以重载的,⽐如cout在输出⼀个变量的时候,能接受不同类型的数据并输出,他就是重载了<<运算符,这个就是运算符重载3.所以运算符重载指的是对已有的运算符重新定义新的运算规则,以适应不同的数据类型,当然重载之后之前的运算规则还是有的2、为什么要进⾏运算符重载1.运算符重载之后可以让运算符去适应不同的数据类型,对于基本数据类型,系统给出了运算符的操作规则,对于⾃定义数据类型来说,系统不知道该给出什么规则class student{int id;int age;char name[20];public:student(int id,int age,const char* name){this->id=id;this->age=age;strcpy(this->name,name);}}student stu1(1,23,"张三");student stu2(2,24,"李四");stu1+stu2;//如果是这样相加,那么应该加的是什么呢?编译器是不知道的,所以编译器就提供了运算符重载这个机制,让⽤户⾃定义运算符的运算规则⼆、运算符重载1、运算符重载类中定义1.关键字:operator,通过关键字来定义运算符重载(跟写个函数⼀样)2.定义:函数返回值类型 operator 要加载的运算符(参数列表){函数体;}这⾥把运算符的使⽤,理解为调⽤函数,只是和平时的调⽤函数有⼀点区别#include<iostream>#include<string>using namespace std;class student{int id;int age;string name;public:student(int age){this->age = age;id = 1;name = "sss ";}student(int id, int age, string name){this->id = id;this->age = age;this->name = name;}void showstudent(){cout << id << "\t" << age << "\t" << name << endl;}student operator+(student& p1)//这个函数会返回⼀个新的对象{int x=this->age + p1.age;student p(x);return p;//返回的是⼀个对象,会调⽤拷贝构造}int operator-(int x){return this->id - x;}void operator+(student&p2){cout << this->id + p2.id << endl;}};//1.操作这个运算符之后,返回值类型是什么int main(){student p1(0, 1, "yunfei");int x = p1.operator-(1);cout << x << endl;student stu1(1, 23, "张三");student stu2(2, 24, "李四");//student stu3 = stu1.operator+(stu2);//student stu3 = stu1 + stu2;stu1 + stu2;//stu3.showstudent();system("pause");return 0;}注意:因为我们这个运算符是在类中写的,所以是通过对象调⽤的,那么this指针会占⼀个参数,⽽且是第⼀个参数,也就是说我们重载⼀个运算符,是在类中,⽽这个运算符是个单⽬运算符,那么参数列表就不⽤写东西了,是双⽬运算符,那么就需要传另⼀个参数进来绝⼤部分的运算符重载都可以参照上⾯这个+号重载2、运算符重载的特点1.⼏乎所有的运算符都可以被重载,除了 . :: ()?() ) sizeof()2.运算符重载基本出现在类中和结构体中3.运算符可以理解为函数的⼀个表现3、运算符重载的注意事项1.重载运算符,这个重载的运算符还是满⾜原来的原则,但不能说重载+号,结果做的事-号的事,这样会使运算符的运⽤上增加很⼤的难度2.运算符重载的参数,类中重载调⽤对象会占⼀个参数,就是this会占⼀个参数,参数列表就是⽤来表⽰运算符的操作的3.对于运算符重载的调⽤,可以直接使⽤运算符,也可以通过对象 . 出来调⽤4.考虑返回值,不同的运算符有不同的返回值,要记得满⾜运算符原来的规则4、使⽤友元函数,实现运算符重载1.类在已经实现且部分修改的情况下下,需要进⾏运算符重载,就可以通过友元的⽅式来进⾏重载#include<iostream>#include<string>using namespace std;class person{int id;int age;string name;public:person(int id, int age, string name){this->id = id;this->age = age;this->name = name;}void showperson(){cout << id << "\t" << age << "\t" << name << endl;}friend int operator+(person&p1, person&p2);};//形参使⽤的是类对象的引⽤,在实参传对象的时候不会调⽤拷贝构造int operator+(person&p1, person&p2){return p1.id + p2.id;}//1.操作这个运算符之后,返回值类型是什么int main(){person stu1(1, 23, "张三");person stu2(2, 24, "李四");int x = operator+(stu1, stu2);//显⽰调⽤int y = stu1 + stu2;//隐式调⽤cout << x << endl << y << endl;system("pause");return 0;}容器:#include<iostream>#include<vector>using namespace std;int main(){//int 是v1这个容器存的类型vector<int> v1;for (int i = 0; i < 10; i++){//push_back()是⼀个函数,功能是尾插元素v1.push_back(i + 1);}for (int i = 0; i < 10; i++){cout << v1[i] << "\t";}system("pause");return 0;}左移右移运算符重载:#include<iostream>using namespace std;class person{int id;public:person(int id){this->id = id;}friend ostream& operator<<(ostream& os, person& p1);friend istream & operator>>(istream & in, person & p2);};//左移右移运算符重载,必须在类外重载,通过友元实现ostream& operator<<(ostream& os, person& p1)//左移运算符{os << p1.id << endl;return os;//返回的是⼀个cout,⽽且只能⽤引⽤}istream & operator>>(istream & in, person & p2)//右移运算符{in >> p2.id;return in;}int main(){person p1(10), p2(20);cin >> p1 >> p2;cout << p1 << endl << p2 << endl;system("pause");return 0;}前++,后++运算符重载:#include<iostream>using namespace std;class person{int id;public:person(int id){this->id = id;}person& operator++()//前++{this->id++;return *this;}person& operator++(int)//后++,int是⼀个占位符,⽤来区分前++和后++的{static person temp = *this;//引⽤不能返回局部变量,要⽤静态变量this->id++;return temp;}friend ostream& operator<<(ostream& os, person& p1);friend istream & operator>>(istream & in, person & p2);};//左移右移运算符重载,必须在类外重载,通过友元实现ostream& operator<<(ostream& os, person& p1)//左移运算符{os << p1.id << endl;return os;//返回的是⼀个cout,⽽且只能⽤引⽤}istream & operator>>(istream & in, person & p2)//右移运算符{in >> p2.id;return in;}int main(){person p1(10), p2(20);//cin >> p1 >> p2;//cout << p1 << endl << p2 << endl;cout << p1 ;//10cout << p1++ ;//10cout << p1 ;//11cout << ++p1 ;//12cout << p1 ;//12system("pause");return 0;}等号运算符重载:#include<iostream>using namespace std;class person{char* name;public:person(const char* name){this->name = new char[strlen(name) + 1];strcpy(this->name, name);}person& operator=(person&p1)//⽤不⽤引⽤传参,要看返回的对象会不会消失 {if (this->name != NULL){delete[]this->name;this->name = NULL;}this->name = new char[strlen() + 1];strcpy(this->name, );return *this;}void show(){cout << name << endl;}~person()//如果有申请函数,就要加上析构函数{if (name != NULL){delete[]name;name = NULL;}}};int main(){{person p1("张三"), p2("李四"), p3("王五");p1 = p2 = p3;p1.show();p2.show();p3.show();}//加上⼤括号,让对象死亡,就能调⽤析构函数system("pause");return 0;}智能指针和==号运算符重载:#include<iostream>using namespace std;class person{int id;public:person(int id){this->id = id;}void show(){cout << id << endl;}bool operator==(person& p){return this->id == p.id;}~person(){cout << "person的析构函数" << endl;}};class smartpointer{person* ps;//包含你要new出来的对象的类的指针public:smartpointer(person* p){ps = p;}//重载->person* operator->()//传回来的是地址,不是对象,不⽤引⽤{return ps;}//重载*person& operator*()//返回的是对象,会调⽤拷贝构造,所以⽤返回值⽤引⽤,就不会再调⽤拷贝构造了 {return *ps;//得到⼀个对象,}~smartpointer(){if (ps != NULL){delete ps;ps = NULL;}}};int main(){{smartpointer p(new person(5));p->show();(*p).show();person p1(1), p2(3);cout << (p1 == p2) << endl;}//有三个对象,所以析构函数执⾏了三次system("pause");return 0;}[]运算符重载:#include<iostream>using namespace std;class person{char* name;public:person(const char* name){this->name = new char[strlen(name) + 1];strcpy(this->name, name);}char& operator[](int index){return name[index];}~person(){if (name != NULL){delete[]name;name = NULL;}cout << "这是析构函数" << endl;}};int main(){person p("asdfg");cout << p[3] << endl;system("pause");return 0;}c++引⽤作为函数返回值:1.以引⽤返回函数值,定义函数时需要在函数名前加 &2.⽤引⽤返回⼀个函数值的最⼤好处是,在内存中不产⽣被返回值的副本3.返回值为引⽤的时候,返回的是⼀个地址,隐形指针4.当返回值不是引⽤时,编译器会专门给返回值分配出⼀块内存的引⽤作为返回值,必须遵守以下规则:(1)不能返回局部变量的引⽤。

C++学习之路—运算符重载(二)运算符重载作为类的成员函数和友元函数

C++学习之路—运算符重载(二)运算符重载作为类的成员函数和友元函数

C++学习之路—运算符重载(⼆)运算符重载作为类的成员函数和友元函数对运算符重载的函数有两种处理⽅式:(1)把运算符重载的函数作为类的成员函数;(2)运算符重载的函数不是类的成员函数,在类中把它声明为友元函数。

1 把运算符重载函数作为类的成员函数例1:为了便于说明问题,将重载函数的定义重写如下:1: Complex Complex :: operator + ( Complex& c2 )2: {3: Complex c ;4: c.real = real + c2.real ;5: c.imag = imag + c2.imag ;6:return c ;7: }有⼈可能会提出这样的疑问:“+”是双⽬运算符,为什么重载函数只有⼀个参数呢?实际上,运算符重载函数应当有两个参数,但是,由于重载函数是Complex类中的成员函数,因此有⼀个参数是隐含的,运算符函数是⽤this指针隐式的访问类对象的成员。

可以看到operator+访问了两个对象中的成员,⼀个是this指针指向的对象中的成员,⼀个是形参对象中的成员。

2 把运算符重载函数作为类的友元函数运算符重载函数除了可以作为类的成员函数外,还可以是⾮成员函数。

在有关的类中把它声明为友元函数,即友元运算符重载函数。

例2:将运算符+重载为适⽤于复数加法,重载函数不作为成员函数,⽽放在类外,作为Complex类的友元函数。

1:class Complex2: {3:public:4: ...5:friend Complex operator + ( Complex& c1 , Complex& c2 ) ; //重载函数作为友元函数6:private:7:double real ;8:double imag ;9: };10:11: Complex operator + ( Complex& c1 , Complex& c2 ) //定义运算符+重载函数12: {13: Complex c ;14: c.real = c1.real + c2.real ;15: c.imag = c1.imag + c2.imag ;16:return c ;17: }这个程序和把运算符重载函数作为类的成员函数相⽐,只做了⼀处改动,就是将运算符重载函数作为类外的普通函数,并在Complex类中声明它为友元函数。

C++运算符重载(简单易懂)

C++运算符重载(简单易懂)

C++运算符重载(简单易懂)运算符重载,就是对已有的运算符重新进⾏定义,赋予其另⼀种功能,以适应不同的数据类型。

你可以重定义或重载⼤部分 C++ 内置的运算符。

例如 + 、 - 、 * 、 / 、++、--、>>、<<等,这样,你就能使⽤⾃定义类型的运算符。

运算符重载的基本格式重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。

与其他函数⼀样,重载运算符有⼀个返回类型和⼀个参数列表。

Point operator+(const Point &);运算符重载有两种⽅式:⼀种是类内重载(运算符重载函数作为类的成员函数),另⼀种是类外重载(运算符重载函数作为类的友元函数)类内重载#include <iostream>using namespace std;class Point{public:Point(){};Point (int x, int y): x(x),y(y) {};Point operator+(const Point &a){ //类内重载,运算符重载函数作为类的成员函数Point ret;ret.x = this->x + a.x;ret.y = this->y + a.y;return ret;}int x,y;};int main() {Point a(2,4),b(5,3);Point c = a + b;cout<< "x :" << c.x << endl;cout<<"y :" << c.y << endl;}当上⾯的代码被编译和执⾏时,它会产⽣下列结果:x : 7y: 7运算符重载是类内重载时,运算符重载函数作为类的成员函数,以上述代码为例 a + b 相当于 a 对象调⽤+⽅法并且传⼊参数时 b 对象类外重载#include <iostream>using namespace std;class Point{public:Point(){};Point (int x, int y): x(x),y(y) {};friend Point operator+(const Point &, const Point &);int x,y;};Point operator+(const Point &a,const Point &b){//类外重载,运算符重载函数作为类的友元函数Point ret;ret.x = a.x + b.x;ret.y = a.y + b.y;return ret;}int main() {Point a(2,4),b(5,3);cout<< "x :" << c.x << endl;cout<<"y :" << c.y << endl;}当上⾯的代码被编译和执⾏时,它会产⽣和上⾯⼀样的结果各种运算符重载实例下⾯将进⾏各种运算符重载实例的代码演⽰,演⽰⼏种基本的运算符重载。

C++运算符重载知识点总结

C++运算符重载知识点总结

C++运算符重载知识点总结C++运算符重载知识总结5.1编译时的多态性与运⾏时的多态性在C++中,多态性的实现和联编(也叫绑定)这⼀概念有关。

源程序—>编译、连接—>可执⾏⽂件这⼀过程时把可执⾏代码联编在⼀起的过程。

其中在运⾏之前就完成的联编叫做静态联编,⼜叫前期联编;⽽在程序运⾏时才完成的联编叫动态联编,也叫后期联编。

静态联编(前期联编):指系统在编译时就决定如何实现某⼀动作。

要求在编译时就知道调⽤函数的全部信息。

静态联编⽀持的多态性成为编译时多态性(静态多态性),通过函数重载(包括运算符重载)和模板实现。

优点:函数调⽤速度很快,效率⾼。

动态联编(后期联编):指系统在运⾏时动态实现某⼀动作。

采⽤这种联编⽅式,⼀直要到程序运⾏时才能确定调⽤哪个函数。

动态联编⽀持的多态性成为运⾏时多态性(动态多态性),通过虚函数实现。

优点:提供了更好的灵活性、问题抽象性和程序易维护性。

5.2运算符重载5.2.1在类外定义的运算符重载函数为了表达上的⽅便,⼈们希望预定义的运算符(如+、-、*、/等)在特定的对象上以新的含义进⾏解释,如希望能够实现两个复数类的加减,这就需要通过运算符重载来解决。

C++中进⾏运算符重载时,必须定义⼀个运算符重载函数,其名字为operator,后随⼀个要重载的运算符。

#includeusing namespace std;class Complex{public:double real;double imag;Complex(double r=0,double i=0){real=r;imag=i;}};Complex operator+(Complex co1,Complex co2)//类外定义运算符+的重载函数{Complex temp;temp.real=co1.real+co2.real;temp.imag=co1.imag+co2.imag;return temp;}int main(){Complex com1(1.1,2.2),com2(3.3,4.4),total1,total2;total1=operator+(com1,com2);//运算符重载函数第⼀种调⽤⽅式,显式调⽤cout<<"real1="<total2=com1+com2;//运算符重载函数第⼆种调⽤⽅式,隐式调⽤cout<<"real2="<return0;}C++语⾔对运算符重载制定了以下⼀些规则:1.绝⼤部分运算符可以重载,不能重载的只有以下⼏个:2.3.运算符重载是针对新类型数据的实际需要,不建议改变原运算符的含义。

运算符重载解读

运算符重载解读

02
在重载运算符时,应明确指定 运算符的参数类型和返回类型 ,避免与其他操作符混淆。
03
在重载运算符时,应尽量使用 有意义的操作符名称,以提高 代码的可读性。
考虑性能和效率
01
02
03
运算符重载时,应考虑 性能和效率,避免对原 有代码造成不必要的性
能损失。
在重载运算符时,应尽 量减少额外的计算和内 存开销,以提高代码的
一元运算符重载
一元运算符重载是指对一元运算符进行重载,使其能够应用于一个操作数。例如,在C中,我们可以 重载一元减号运算符(-)来返回一个数的相反数。
常见的一元运算符有:+、-、~、!等。
二元运算符重载
二元运算符重载是指对二元运算符进行重载,使其能够应用于两个操作数。例如,在C中,我们可以重载加号运算符(+)来定 义两个自定义类型的相加行为。
01
提高代码可读性
运算符重载可以使代码更易读, 因为运算符的使用可以使代码更 简洁、更直观。
02
03
方便函数调用
运算符重载可以使得函数调用更 加方便,因为运算符的使用可以 减少函数调用的开销。
04
缺点分析
易造成混淆
运算符重载可能会使得代码难以理解,因为 运算符的行为可能会被改变,导致读者难以
理解代码的含义。
常见的二元运算符有:+、-、*、/、%等。
三元运算符重载
三元运算符重载是指对三元运算符进行重载,使其能够应用于三个操作数。例如,在C中,我们可以重载条件运 算符(?)来定义一个自定义类型的条件判断行为。
常见的三元运算符有:?:。
03
运算符重载的常见场景
类与类之间的运算
01
两个类对象之间的加法运算,可以表示它们之间的某种关联或 合并。

运算符重载详解

运算符重载详解

运算符重载详解1.运算符重载定义:C++中预定义的运算符的操作对象只能是基本数据类型。

但实际上,对于许多⽤户⾃定义类型(例如类),也需要类似的运算操作。

这时就必须在C++中重新定义这些运算符,赋予已有运算符新的功能,使它能够⽤于特定类型执⾏特定的操作。

运算符重载的实质是函数重载,它提供了C++的可扩展性,也是C++最吸引⼈的特性之⼀。

运算符重载是通过创建运算符函数实现的,运算符函数定义了重载的运算符将要进⾏的操作。

运算符函数的定义与其他函数的定义类似,惟⼀的区别是运算符函数的函数名是由关键字operator和其后要重载的运算符符号构成的。

运算符函数定义的⼀般格式如下:<返回类型说明符> operator <运算符符号>(<参数表>){<函数体>} 2.运算符重载时要遵循以下规则:(1) 除了类属关系运算符"."、成员指针运算符".*"、作⽤域运算符"::"、sizeof运算符和三⽬运算符"?:"以外,C++中的所有运算符都可以重载。

(2) 重载运算符限制在C++语⾔中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符。

(3) 运算符重载实质上是函数重载,因此编译程序对运算符重载的选择,遵循函数重载的选择原则。

(4) 重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构。

(5) 运算符重载不能改变该运算符⽤于内部类型对象的含义。

它只能和⽤户⾃定义类型的对象⼀起使⽤,或者⽤于⽤户⾃定义类型的对象和内部类型的对象混合使⽤时。

(6) 运算符重载是针对新类型数据的实际需要对原有运算符进⾏的适当的改造,重载的功能应当与原有功能相类似,避免没有⽬的地使⽤重载运算符。

(7)重载运算符的函数不能有默认的参数,否则就改变了运算符的参数个数,与前⾯第3点相⽭盾了;(8)重载的运算符只能是⽤户⾃定义类型,否则就不是重载⽽是改变了现有的C++标准数据类型的运算符的规则了,会引会天下⼤乱的;(9)⽤户⾃定义类的运算符⼀般都必须重载后⽅可使⽤,但两个例外,运算符“=”和“&”不必⽤户重载;(10)运算符重载可以通过成员函数的形式,也可是通过友元函数,⾮成员⾮友元的普通函数。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

方案二:重载成友员函数
class Rational { friend Rational operator+(const Rational &r1, const Rational &r2); friend Rational operator*(const Rational &r1 , const Rational &r2); friend bool operator<(const Rational &r1 , const Rational &r2) ; friend bool operator==(const Rational &r1 , const Rational &r2); friend bool operator>(const Rational &r1 , const Rational &r2) ; friend bool operator<=(const Rational &r1 , const Rational &r2); friend bool operator>=(const Rational &r1 , const Rational &r2); friend bool operator!=(const Rational &r1 , const Rational &r2) ;
扩充运算符的功能 增强了C++ 语言的可扩充性不是所有的运算符都能重载 重载不能改变运算符的优先级和结合性 重载不能改变运算符的操作数个数 不能创建新的运算符
可以重载的运算符
+ - * / % ^ &| ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- ->* , -> [] () new delete new[] delete[]
重载后有理数类的使用
int main() { Rational r1(1,6), r2(1,6), r3;
r3 = r1 + r2; r1.display(); cout << " + "; r2.display(); cout << " = "; r3.display(); cout << endl; r3 = r1 * r2; r1.display(); cout << " * "; r2.display(); cout << " = "; r3.display(); cout << endl; return 0; }
不能重载的运算符
. .* :: ?: sizeof
第11章 运算符重载
什么是运算符重载 运算符重载的方法 几个特殊的运算符的重载 自定义类型转换运算符 运算符重载实例
运算符重载的方法
运算符重载就是写一个函数解释某个运算符在 某个类中的含义
要使得系统能自动找到重载的这个函数,函数 名必须要体现出和某个被重载的运算符的联系。
函数实现
Rational Rational::operator+(const Rational &r1) const { Rational tmp;
tmp.num = num * r1.den + r1.num * den; tmp.den = den * r1.den; tmp.ReductFraction(); return tmp; }
第11章77 运算符重载
什么是运算符重载
使系统内置的运算符可以用于类类型 例如:+ 运算符能够实现2个对象间的加。
例如:类A的对象a1、a2、a3,希望: a3 = a1 + a2; 即:分别把对象a1和a2的各个数据成员值 对应相加,然后赋给对象a3。
问题的提出
把某些事交给系统去做,用户只要知道相 加就可
Rational operator*(const Rational &r1, const Rational &r2) { Rational tmp;
tmp.num = r1.num * r2.num; tmp.den = r1.den * r2.den; tmp.ReductFraction(); return tmp; } 其他函数实现略
C++中规定,重载函数名为 operator@ 其中,@为要重载的运算符。如要重载“+”运
算符,该重载函数名为operator+。要重载赋值 运算符,函数名为operator=。
函数原型
运算符的重载不能改变运算符的运算对象数。因此,重载函 数的形式参数个数(包括成员函数的隐式指针this)与运算 符的运算对象数相同
运算符重载可以重载成成员函数也可以重载成全局函数实现。 重载成全局函数时,最好把此函数设为友员函数
如果作为类的成员函数,它的形式参数个数比运算符的运算 对象数少1。这是因为成员函数有一个隐含的参数this。在 C++中,把隐含参数this作为运算符的第一个参数。
当把一个一元运算符重载成成员函数时,该函数没有形式参 数。
bool Rational::operator>=(const Rational &r1) const { return num * r1.den >= den * r1.num; }
bool Rational::operator!=(const Rational &r1) const { return !(*this == r1);}
};
函数的实现
Rational operator+(const Rational &r1, const Rational &r2) { Rational tmp;
tmp.num = r1.num * r2.den + r2.num * r1.den; tmp.den = r1.den * r2.den; tmp.ReductFraction(); return tmp; }
把一个二元运算符重载成成员函数时,该函数只有一个形式 参数,就是右操作数,当前对象是左操作数。
重载实例
为rational类增加“+”和“*”以及比较的重 载函数,用以替换现有的add和multi函数
方案一:重载成成员函数
class Rational { private:
int num; int den; void ReductFraction(); public: Rational(int n = 0, int d = 1) { num = n; den = d;}
赋值运算符重载和拷贝构造函数
一般来讲,需要拷贝构造函数的类也需要 重载赋值运算符
定义对象时给对象赋初值调用的是拷贝构 造函数
程序的语句部分中的赋值语句调用的是赋 值运算符重载函数
几个特殊的运算符的重载
赋值运算符 下标运算符 函数调用运算符 ++和—运算符的重载 重载函数的原型设计考虑 输入输出运算符重载
bool Rational::operator<(const Rational &r1) const { return num * r1.den < den * r1.num; }
bool Rational::operator==(const Rational &r1) const { return num == r1.num && den == r1.den;}
会引起内存泄漏 使这两个数组的元素存放于同一块空间中
当这两个对象析构时,先析构的对象会释放 存储数组元素的空间。而当后一个对象析构 时,无法释放存放数组元素的空间
赋值运算符“=”的原型
赋值运算符只能重载成成员函数 函数原型:
X &X::operator=(const X &source) { // 赋值过程 }
private: int num; int den; void ReductFraction();
public: Rational(int n = 0, int d = 1) { num = n; den = d;} void display() { cout << num << '/' << den;}
bool Rational::operator>(const Rational &r1) const { return num * r1.den > den * r1.num; }
bool Rational::operator<=(const Rational &r1) const { return num * r1.den <= den * r1.num; }
Rational Rational::operator*(const Rational &r1) const { Rational tmp;
tmp.num = num * r1.num; tmp.den = den * r1.den; tmp.ReductFraction(); return tmp; }
以使得应用更加灵活。如果把加运算定义成全局函数,r是 有理数类的对象,则2+r是一个合法的表达式。
第11章 运算符重载
什么是运算符重载 运算符重载的方法 几个特殊的运算符的重载 自定义类型转换运算符 运算符重载实例
几个特殊的运算符的重载
相关文档
最新文档