第11章 运算符重载
11章运算符重载
![11章运算符重载](https://img.taocdn.com/s3/m/8a4b4da6e53a580216fcfe7b.png)
考虑用普通函数实现两个复数相加
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( ); }
第11章 运算符重载
![第11章 运算符重载](https://img.taocdn.com/s3/m/3f229b3d10661ed9ad51f31d.png)
• 这并不会引起任何编译错误,但将引起逻辑上的混乱。 因此,重载一个运算符时,其具体操作还应尽量与该 运算符的原始含义保持一致。
重载一元运算符为类运算符
• 由于类运算符的第一操作数约定为当前对象(隐含),所 以用成员函数实现一元运算符重载的格式为: 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:函数的形参表,即第二操作数。
运算符重载
![运算符重载](https://img.taocdn.com/s3/m/73f47d99998fcc22bdd10d4c.png)
1、多态性的基本概念2、派生类对象替换基类对象3、虚函数的定义4、抽象类的定义5、宠物类的设计6、运算符重载7、日期类对象判断大小8、分数类对象运算符重载☐运算符重载指赋予运算符新的操作功能,主要用于对类的对象的操作☐运算符+意味着多少对象类型的加法呢?☐还可以定义新的对象类型加法☐运算符重载定义形式:<类型><类名>::operator<操作符>(<参数表>){函数体}☐首先定义虚数类☐虚数可以描述为:a+bi☐a与b看成实数,定义成double类型☐成员函数除了构造与析构外,还有:☐输出虚数、修改虚数、得到实部a、得到虚部b ☐相加+、判相等==#include <iostream>using namespace std;class Complex{private:double real, imag;public:Complex(double r = 0, double i = 0): real(r), imag(i){ }double Real(){return real;}double Imag(){return imag;}Complex operator +(Complex&);Complex operator +(double);bool operator ==(Complex);~Complex(){ };Complex Complex::operator +(Complex &c)// 重载运算符+,两边是虚数对象{Complex temp;temp.real = real+c.real;temp.imag = imag+c.imag;return temp;}Complex Complex::operator +(double d)// 重载运算符+,左边是虚数对象,右边是双精度数{Complex temp;temp.real = real+d;temp.imag=imag;return temp;}bool Complex::operator ==(Complex c)// 重载运算符=={if (real == c.real && imag == c.imag)return true;elseint main(){Complex c1(3,4),c2(5,6),c3;cout << "C1 = " << c1.Real() << "+j" << c1.Imag() << endl;cout << "C2 = " << c2.Real() << "+j" << c2.Imag() << endl;c3 = c1+c2;cout << "C3 = " << c3.Real() << "+j" << c3.Imag() << endl;c3 = c3+6.5;cout << "C3 + 6.5 = " << c3.Real() << "+j" << c3.Imag() << endl;if ( c1==c2 )cout<<“两个复数相等”;elsecout<<“两个复数不相等”;return 0;☐运算符++分前置运算符和后置运算符☐例如: ++Y与Y++☐前置运算符定义Complex Complex::operator ++ () {real+=1;return *this;}☐后置运算符定义Complex Complex::operator ++ (int) {real+=1;return *this;}。
第11章运算符重载
![第11章运算符重载](https://img.taocdn.com/s3/m/6a640136a32d7375a4178043.png)
运算符重载函数是类成员函数
一元运算符 @表示要重载的运算符 表示要重载的运算符 隐式调用: 对象名 对象名@ 隐式调用:@对象名 或者 对象名 显示调用:对象.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章运算符重载](https://img.taocdn.com/s3/m/7f040cec5727a5e9846a611e.png)
❖ 把一个二元运算符重载成成员函数时,该函数只有一个形 式参数,就是右操作数,当前对象是左操作数。
程序设计 - 9
重载实例
《程序设计》 cs.sjtu 2011.9
❖ 为rational类增加“+”和“*”以及比较 的重载函数,用以替换现有的add和 multi函数
❖ 运算符的重载不能改变运算符的运算对象数。因此,重载 函数的形式参数个数(包括成员函数的隐式指针this)与运 算符的运算对象数相同
❖ 运算符重载可以重载成成员函数也可以重载成全局函数实 现。重载成全局函数时,最好把此函数设为友员函数
❖ 如果作为类的成员函数,它的形式参数个数比运算符的运 算对象数少1。这是因为成员函数有一个隐含的参数this。 在C++中,把隐含参数this作为运算符的第一个参数。
程序设计 - 11
函数实现
《程序设计》 cs.sjtu 2011.9
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; }
Rational Rational::operator*(const Rational &r1) const
{ Rational tmp;
tmp.num = num * r1.num;
tmp.den = den * r1.den;
tmp.ReductFraction();
Python教程之----第11章-Python的面向对象(上)
![Python教程之----第11章-Python的面向对象(上)](https://img.taocdn.com/s3/m/7a7c9aabc1c708a1284a4492.png)
第11章 面向对象编程(上)
· 面向对象编程 · 类和对象 · 构造方法和析构方法
· self的使用 · 运算符重载
✎ 学习目标
1 了解面向对象编
程思想
掌握类和对象的定义 2
和使用
掌握构造方法的使用
4
掌握self的使用
3
✎ 目录页
01 面向对象编程概述 02 类和对象 03 构造方法和析构方法 04 self的使用 05 运算符重载
print("%s的车在鸣笛..."%(self.color))
✎ 析构方法
• 当删除一个对象来释放类所占用资源的时候, Python解释器默认会调用另外一个方法,这个方 法就是__del__( )方法。
• __del__方法被称为析构方法。
✎ 过渡页
01 面向对象编程概述 02 类和对象 03 构造方法和析构方法 04 self的使用 05 运算符重载
✎ 过渡页
01 面向对象编程概述 02 类和对象 03 构造方法和析构方法 04 self的使用 05 运算符重载
✎ 面向对象
程序员“面向对象”
在现实世界中存在各种不同形态的事物, 这些事物之间存在着各种各样的联系。在程 序中使用对象来映射现实中的事物,使用对 象间的关系来描述事物之间的联系,这种思 想就是面向对象。
✎ self的使用
• 在方法的列表中,第1个参数永远都是self。 • self的字面意思是自己,我们可以把它当做C++里面的
this指针理解,表示的是对象自身。 • 当某个对象调用方法的时候,Python解释器会把这个对
象作为第1个参数传给self,开发者只需要传递后面的参 数就可以了。
运算符重载
![运算符重载](https://img.taocdn.com/s3/m/968add46be1e650e52ea998a.png)
例4.1 通过函数来实现复数相加 #include <iostream> using namespace std; class Complex { private: double real,image; public: Complex() { real=0; image=0; } Complex(double r,double i):real(r),image(i){} Complex complex_add(Complex &c2); void display(); };
4.4 重载运算符函数的设计
• 1. 重载运算符的返回值
–运算符函数的返回值类型一般都与当前类 的类型有关。 –运算符函数返回对象的值还是对象引用
• 原则:如果运算符形成的表达式(函数调用表达 式)需要作为左值则返回引用,否则返回值。
• ⑴+、-、*、/、%、后置的++和-– 因为加法、减法、乘法、除法和后置的加1和减1表达 式不能做左值,重载时应返回对象的值,故应采用类 似如下的函数原型: – Complex operator+(...); – Complex operator++(...);
+ ^ =
& <
* | >
/ ~ +=
% ! -=
*= |= == || ->
/= << != ++ []
%= >> <= -()
^= >>= >= >* New
&= <<= && , delete
.
.*
::
运算符重载
![运算符重载](https://img.taocdn.com/s3/m/6e74c7b8a45177232e60a234.png)
{
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
运算符重载
![运算符重载](https://img.taocdn.com/s3/m/acac424cf7ec4afe04a1df6c.png)
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指针自由地访问本类 的数据成员, 的数据成员,因此可以少写一个函数 的参数。 的参数。但必须要求运算表达式第一 个参数(即运算符左侧的操作数) 个参数(即运算符左侧的操作数)是一 个类对象, 个类对象,而且与运算符函数的类型 相同。 相同。因为必须通过类的对象去调用 该类的成员函数,而且只有运算符重 该类的成员函数, 载函数返回值与该对象同类型, 载函数返回值与该对象同类型,运算 结果才有意义。 结果才有意义。
运算符重载
![运算符重载](https://img.taocdn.com/s3/m/b0093576f46527d3240ce0ec.png)
运算符重载为类的友元函数
类中的声明: 类中的声明: friend 函数类型 operator 运算符(参数表); 运算符(参数表); 运算符重载函数的定义形式: 运算符重载函数的定义形式: 运算符(参数表) 函数类型 operator 运算符(参数表) { 函数体; 函数体; } 附加例) (附加例)用友元函数实现复数的加法运算符的重 载。
数据类型转换 标准数据类型转换
隐式转换: 自动转成double型) 隐式转换:7.5+2 (将2自动转成 将 自动转成 型 显式转换: 转成整型) 显式转换:int(89.5) (将89.5转成整型 将 转成型
涉及到类类型的转换
对于用户自己声明的类型, 对于用户自己声明的类型,编译系统并不知道怎样进行转 换。解决这个问题的关键是让编译系统知道怎样去进行转 换,需要定义专门的处理函数。 需要定义专门的处理函数。 将一个其他类型的数据转换成一个类类型: 将一个其他类型的数据转换成一个类类型:转换构造函数 将一个类的对象转换成另一类型的数据: 将一个类的对象转换成另一类型的数据:类型转换函数
运算符重载的格式
运算符重载为类的成员函数 运算符重载为类的友元函数
运算符重载的规则
①
② ③ ④ ⑤
.”、 *” ::”、 ?:”和 sizeof”等几个运 除“. 、“*”、“:: 、“?: 和“sizeof 等几个运 算符不能重载外, 算符不能重载外,C++中几乎所有的运算符都可以 中几乎所有的运算符都可以 重载。 重载。 运算符被重载后,其优先级和结合性不会改变。 运算符被重载后,其优先级和结合性不会改变。 不能改变运算符操作对象的个数。 不能改变运算符操作对象的个数。 运算符的意义应不变。 运算符的意义应不变。 用于类对象的运算符一般必须重载,但有两个例外, 用于类对象的运算符一般必须重载,但有两个例外, 运算符“ 和 不必用户重载。 运算符“=”和“&”不必用户重载。 不必用户重载
第11章77 运算符重载
![第11章77 运算符重载](https://img.taocdn.com/s3/m/e47e8c9f0722192e4436f627.png)
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[]
运算符重载——精选推荐
![运算符重载——精选推荐](https://img.taocdn.com/s3/m/f96b2cc077a20029bd64783e0912a21614797fad.png)
运算符重载运算符重载学习运算符重载,让运算符能做⼀些原来做不了的事情,⽅便它的使⽤⼀、运算符重载的概念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)不能返回局部变量的引⽤。
运算符重载
![运算符重载](https://img.taocdn.com/s3/m/e8b3b6c64028915f804dc288.png)
万象城春节营销方案万象城春节营销方案一、背景介绍春节是中国传统的重要节日之一,也是全年销售额最高的时期之一。
随着消费水平的提高和消费观念的改变,人们在春节期间不仅满足于传统的购物需求,更加注重消费体验和品牌形象。
作为一家位于城市商圈的综合购物中心,万象城需要制定一套有吸引力、创新性的春节营销方案,提升品牌形象、增加销售额。
二、目标和定位1. 主要目标:增加春节期间销售额,提升品牌形象。
2. 定位:高端购物中心、高品质消费场所。
三、核心信息1. 品牌核心信息:高品质、多元、高端。
2. 营销信息:新年新气象,尽享购物乐趣。
四、理念和创意1. 理念:为顾客带来春节购物的新鲜元素,打造愉悦、独特的购物体验,让他们惊喜连连,享受购物乐趣。
2. 创意:结合传统与现代、东西方文化相融合,以独特的方式展现春节主题,吸引顾客的注意力。
五、活动策划1. 主题活动活动一:万象迎春晚会活动时间:春节前一天晚上活动地点:万象城中心广场活动内容:- 邀请知名主持人和明星嘉宾,举办一场充满欢乐、娱乐性的晚会。
演唱、舞蹈、小品、魔术等形式丰富多样。
- 晚会通过现场直播和社交媒体推广,吸引更多人关注和参与,增加品牌曝光。
- 晚会现场设置特色互动游戏,如抽奖、发红包等,增加顾客参与度,扩大品牌影响力。
活动二:文化体验展览活动时间:春节期间活动地点:万象城大堂及商铺内部活动内容:- 展览展示中国传统文化艺术,如中国书法、民俗文化、剪纸等。
- 安排专业讲解员,向顾客介绍传统文化背景和艺术品鉴赏技巧。
- 设置DIY手工坊,让顾客亲身参与传统艺术品制作,增加消费者的体验感。
活动三:花灯巡游活动时间:春节期间活动地点:万象城周边街区活动内容:- 邀请民间艺术团队表演传统舞蹈、武术,穿着中国传统服装,带着花灯游历街区。
- 设立观众席供顾客观看,并提供中国传统小吃、特色饮品等,让顾客在观看表演的同时,感受传统文化的美味。
2. 营销推广活动- 春节福袋:顾客在万象城购物满一定金额可以领取春节福袋,福袋内含有不同价值的现金券和特别优惠券,鼓励顾客消费,增加销售额。
运算符重载——精选推荐
![运算符重载——精选推荐](https://img.taocdn.com/s3/m/d8cec3c4370cba1aa8114431b90d6c85ec3a8880.png)
运算符重载什么是运算符的重载?运算符与类结合,产⽣新的含义。
为什么要引⼊运算符重载?作⽤:为了实现类的多态性(多态是指⼀个函数名有多种含义)怎么实现运算符的重载?⽅式:类的成员函数或友元函数(类外的普通函数)规则:不能重载的运算符有 . 和 .* 和 ?: 和 :: 和 sizeof友元函数和成员函数的使⽤场合:⼀般情况下,建议⼀元运算符使⽤成员函数,⼆元运算符使⽤友元函数1、运算符的操作需要修改类对象的状态,则使⽤成员函数。
如需要做左值操作数的运算符(如=,+=,++)2、运算时,有数和对象的混合运算时,必须使⽤友元3、⼆元运算符中,第⼀个操作数为⾮对象时,必须使⽤友元函数。
如输⼊输出运算符<<和>>具体规则如下:运算符建议使⽤所有⼀元运算符成员函数= ( ) [ ] ->必须是成员函数+= -= /= *= ^= &= != %= >>= <<= , 似乎带等号的都在这⾥了成员函数所有其它⼆元运算符, 例如: –,+,*,/友元函数<< >>必须是友元函数2. 参数和返回值当参数不会被改变,⼀般按const引⽤来传递(若是使⽤成员函数重载,函数也为const).对于返回数值的决定:1) 如果返回值可能出现在=号左边, 则只能作为左值, 返回⾮const引⽤。
2) 如果返回值只能出现在=号右边, 则只需作为右值, 返回const型引⽤或者const型值。
3) 如果返回值既可能出现在=号左边或者右边, 则其返回值须作为左值, 返回⾮const引⽤。
运算符重载举例:+和 -运算符的重载:class Point{private:int x;public:Point(int x1){ x=x1;}Point(Point& p){ x=p.x;}const Point operator+(const Point& p);//使⽤成员函数重载加号运算符friend const Point operator-(const Point& p1,const Point& p2);//使⽤友元函数重载减号运算符};const Point Point::operator+(const Point& p){return Point(x+p.x);}Point const operator-(const Point& p1,const Point& p2){return Point(p1.x-p2.x);}输出:Point a(1);Point b(2);a+b; //正确,调⽤成员函数a-b; //正确,调⽤友元函数a+1; //正确,先调⽤类型转换函数,把1变成对象,之后调⽤成员函数a-1; //正确,先调⽤类型转换函数,把1变成对象,之后调⽤友元函数1+a; //错误,调⽤成员函数时,第⼀个操作数必须是对象,因为第⼀个操作数还有调⽤成员函数的功能1-a; //正确,先类型转换后调⽤友元函数总结:1、由于+ -都是出现在=号的右边,如c=a+b,即会返回⼀个右值,可以返回const型值2、后⼏个表达式讨论的就是,数和对象混合运算符的情况,⼀般出现这种情况,常使⽤友元函数3、双⽬运算符的重载:重载运算符函数名:operator@(参数表)隐式调⽤形式:obj1+obj2显式调⽤形式:obj1.operator+(OBJ obj2)---成员函数operator+(OBJ obj1,OBJ obj2)---友元函数执⾏时,隐式调⽤形式和显式调⽤形式都会调⽤函数operator+()++和--运算符的class Point{private:int x;public:Point(int x1){ x=x1;}Point operator++();//成员函数定义⾃增const Point operator++(int x); //后缀可以返回⼀个const类型的值friend Point operator--(Point& p);//友元函数定义--friend const Point operator--(Point& p,int x);//后缀可以返回⼀个const类型的值};Point Point::operator++()//++obj{x++;return *this;}const Point Point::operator++(int x)//obj++{Point temp = *this;this->x++;return temp; // 需要返回⼀个临时对象,效率不如 ++obj ⾼}Point operator--(Point& p)//--obj{p.x--;return p;//前缀形式(--obj)重载的时候没有虚参,通过引⽤返回*this 或⾃⾝引⽤,也就是返回变化之后的数值}const Point operator--(Point& p,int x)//obj--{Point temp = p;p.x--;return temp;// 后缀形式obj--重载的时候有⼀个int类型的虚参, 返回原状态的拷贝}调⽤:Point b(2);a++;//隐式调⽤成员函数operator++(0),后缀表达式++a;//隐式调⽤成员函数operator++(),前缀表达式b--;//隐式调⽤友元函数operator--(0),后缀表达式--b;//隐式调⽤友元函数operator--(),前缀表达式cout<<a.operator ++(2);//显式调⽤成员函数operator ++(2),后缀表达式cout<<a.operator ++();//显式调⽤成员函数operator ++(),前缀表达式cout<<operator --(b,2);//显式调⽤友元函数operator --(2),后缀表达式cout<<operator --(b);//显式调⽤友元函数operator --(),前缀表达式 </pre>总结:1、a++函数返回:temp(临时变量)函数返回是否是const类型:返回是⼀个拷贝后的临时变量),不能出现在等号的左边(临时变量不能做左值),函数的结果只能做右值,则要返回⼀个const类型的值++a函数返回:*this;函数返回是否是const类型:返回原状态的本⾝,返回值可以做左值,即函数的结果可以做左值,则要返回⼀个⾮const类型的值2、前后缀仅从函数名(operator++)⽆法区分,只能有参数区分,这⾥引⼊⼀个虚参数int x,x可以是任意整数。
运算符重载
![运算符重载](https://img.taocdn.com/s3/m/f272bb4ce518964bcf847c97.png)
• 赋值运算符 赋值运算符(=) – Memberwise assignment between objects • 地址运算符 地址运算符(&) – Returns address of object • 逗号运算符 (,) ,
– 以上三种运算符用于对象时,不需要重载 以上三种运算符用于对象时,
© 2006 Pearson Education, Inc. All rights reserved.
18
软件工程知识11. 软件工程知识 2
运算符函数的参数至少有一个必须是用户自定义 类型的对象或引用。 类型的对象或引用。这样使程序员无法改变运算 符作用在基本类型的对象上的方式。 符作用在基本类型的对象上的方式。
• 有时最好把这些函数定义为类的成员函数(在类的内部) 有时最好把这些函数定义为类的成员函数(在类的内部) • 有时最好定义为类的友元函数(在类的外部) 有时最好定义为类的友元函数(在类的外部) • 在极少数情况下,他们可能既不是成员函数,也不是友元函 在极少数情况下,他们可能既不是成员函数, 数
© 2006 Pearson Education, Inc. All rights reserved.
© 2006 Pearson Education, Inc. All rights reserved.
7
11.2 运算符重载的基础知识
• 运算符重载
– 类的对象要使用运算符的话,运算符必须重载 类的对象要使用运算符的话, – 编写运算符重载函数的形式通常有两种: 编写运算符重载函数的形式通常有两种:
• 仅允许重载(即重新定义)现有的运算符,使它在用于类的 仅允许重载(即重新定义)现有的运算符, 对象时具有新类型的含义
运算符重载解读
![运算符重载解读](https://img.taocdn.com/s3/m/b70d6f29cbaedd3383c4bb4cf7ec4afe04a1b186.png)
02
在重载运算符时,应明确指定 运算符的参数类型和返回类型 ,避免与其他操作符混淆。
03
在重载运算符时,应尽量使用 有意义的操作符名称,以提高 代码的可读性。
考虑性能和效率
01
02
03
运算符重载时,应考虑 性能和效率,避免对原 有代码造成不必要的性
能损失。
在重载运算符时,应尽 量减少额外的计算和内 存开销,以提高代码的
一元运算符重载
一元运算符重载是指对一元运算符进行重载,使其能够应用于一个操作数。例如,在C中,我们可以 重载一元减号运算符(-)来返回一个数的相反数。
常见的一元运算符有:+、-、~、!等。
二元运算符重载
二元运算符重载是指对二元运算符进行重载,使其能够应用于两个操作数。例如,在C中,我们可以重载加号运算符(+)来定 义两个自定义类型的相加行为。
01
提高代码可读性
运算符重载可以使代码更易读, 因为运算符的使用可以使代码更 简洁、更直观。
02
03
方便函数调用
运算符重载可以使得函数调用更 加方便,因为运算符的使用可以 减少函数调用的开销。
04
缺点分析
易造成混淆
运算符重载可能会使得代码难以理解,因为 运算符的行为可能会被改变,导致读者难以
理解代码的含义。
常见的二元运算符有:+、-、*、/、%等。
三元运算符重载
三元运算符重载是指对三元运算符进行重载,使其能够应用于三个操作数。例如,在C中,我们可以重载条件运 算符(?)来定义一个自定义类型的条件判断行为。
常见的三元运算符有:?:。
03
运算符重载的常见场景
类与类之间的运算
01
两个类对象之间的加法运算,可以表示它们之间的某种关联或 合并。
运算符重载详解
![运算符重载详解](https://img.taocdn.com/s3/m/c1a011846429647d27284b73f242336c1eb930eb.png)
运算符重载详解1.运算符重载定义:C++中预定义的运算符的操作对象只能是基本数据类型。
但实际上,对于许多⽤户⾃定义类型(例如类),也需要类似的运算操作。
这时就必须在C++中重新定义这些运算符,赋予已有运算符新的功能,使它能够⽤于特定类型执⾏特定的操作。
运算符重载的实质是函数重载,它提供了C++的可扩展性,也是C++最吸引⼈的特性之⼀。
运算符重载是通过创建运算符函数实现的,运算符函数定义了重载的运算符将要进⾏的操作。
运算符函数的定义与其他函数的定义类似,惟⼀的区别是运算符函数的函数名是由关键字operator和其后要重载的运算符符号构成的。
运算符函数定义的⼀般格式如下:<返回类型说明符> operator <运算符符号>(<参数表>){<函数体>} 2.运算符重载时要遵循以下规则:(1) 除了类属关系运算符"."、成员指针运算符".*"、作⽤域运算符"::"、sizeof运算符和三⽬运算符"?:"以外,C++中的所有运算符都可以重载。
(2) 重载运算符限制在C++语⾔中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符。
(3) 运算符重载实质上是函数重载,因此编译程序对运算符重载的选择,遵循函数重载的选择原则。
(4) 重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构。
(5) 运算符重载不能改变该运算符⽤于内部类型对象的含义。
它只能和⽤户⾃定义类型的对象⼀起使⽤,或者⽤于⽤户⾃定义类型的对象和内部类型的对象混合使⽤时。
(6) 运算符重载是针对新类型数据的实际需要对原有运算符进⾏的适当的改造,重载的功能应当与原有功能相类似,避免没有⽬的地使⽤重载运算符。
(7)重载运算符的函数不能有默认的参数,否则就改变了运算符的参数个数,与前⾯第3点相⽭盾了;(8)重载的运算符只能是⽤户⾃定义类型,否则就不是重载⽽是改变了现有的C++标准数据类型的运算符的规则了,会引会天下⼤乱的;(9)⽤户⾃定义类的运算符⼀般都必须重载后⽅可使⽤,但两个例外,运算符“=”和“&”不必⽤户重载;(10)运算符重载可以通过成员函数的形式,也可是通过友元函数,⾮成员⾮友元的普通函数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
► 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)
“obj1 op obj2” ► 相当于obj1.operator op(obj2)
► 经过重载后,表达式
6
【例39.1】设计一个复数类,实现该类对象的加法和减法运算。
imag=i;}
//构造函
7 complex operator ++(int); //重载后置++ 8 void display() 9 { 10 cout<<real<<"+"<<imag<<"i"<<endl; 11 } 12 private: 13 double real; //实部 14 double imag; //虚部 15 };
1 #include <iostream> 2 using namespace std; 3 class complex 4 //复数类 { 5 public: 6 complex(double r=0.0,double i=0.0){real=r; imag=i;}//构造函数 7 complex operator +(complex &c2); //重载+运算符 8 complex operator -(complex &c2); //重载-运算符 9 void display() 10 { 11 cout<<real<<"+"<<imag<<"i"<<endl; 12 } 13 private: 14 double real; //实部 15 double imag; //虚部 16 };
运算符号(形式参数列表); 运算符号(形式参数列表)
4
► 当运算符重载为成员函数时,运算符函数的形式参数的个数比运算
符规定的运算对象个数要少一个。
► 原因是类的非静态成员函数都有一个隐含的this指针,运算符函数
可以用this指针隐式地访问类对பைடு நூலகம்的成员,因此这个对象自身的数 据可以直接访问,不需要放到形参列表中进行传递,少了的运算对 象就是该对象本身。
算符,但在输出操作中又是与流对象cout配合是的流插入运算符, >>运算符也是。
► C++允许程序员重载大部分运算符,使运算符符合所在的上下文环
境。虽然重载运算符的任务也可以通过显式的函数调用来完成,但 是使用运算符重载往往使程序更清晰。
4
► 本质上,运算符重载是函数的重载。重载运算符使具有特殊名称的
8
3、运算符重载为类成员函数 4、运算符重载为友元函数
► 将运算符重载为类的成员函数,一般形式为:
class 类名{ //类体 …… 返回类型 operator 运算符号(形式参数列表) { 函数体 } …… };
3
► 或者:
class
}; 返回类型 类名::operator { 函数体 }
类名{ //类体 … … 返回类型 operator ……
7
17 complex complex::operator +(complex &c2) 18 { complex c; 20 c.real=c2.real+this.real; 21 c.imag=c2.imag+imag; 22 return c; 23 } 24 complex complex::operator -(complex &c2) 25 { complex c; 27 c.real=real-c2.real; //顺序不能颠倒 28 c.imag=imag-c2.imag; 29 return c; 30 } 31 int main() 32 { complex c1(1,2),c2(3,4),c3; 34 36 //输出4+6i c3=c2+c1; c3.display(); c3.display(); 38 //输出2+2i c3=c2-c1; 39 } return 0;
刘玉利,信息科学与工程学院
1、运算符重载的概念 2、运算符函数
► 运算符重载就是对现有的运算符重新进行定义,赋予其另一种功能,
以适应不同的数据类型。
3
► 所谓重载,就是重新赋予新的含义。例如函数重载,就是对一个已
有的函数赋予新的功能。
► C++语言本身就重载了很多运算符,例如<<是位运算中的左移运
11
► 3.
后置单目运算符重载为类的成员函数,形式如下: 返回类型 类名::operator op(int) { …… //this指针对应obj运算对象 }
“obj op” ► 相当于obj.operator op(0)
► 经过重载后,表达式
12
【例39.3】实现复数类的后置自增运算。
1 2 3 4 5 6 数 #include <iostream> using namespace std; class complex //复数类 { public: complex(double r=0.0,double i=0.0) {real=r;
10
16 complex complex::operator ++() 17 { 18 complex a; 19 real++; 20 imag++; 21 a.real=real; 22 a.imag=imag; 23 return a; 24 } 25 int main() 26 { 27 complex c1(1,2),c2; 28 c2=++c1; 29 c1.display(); //输出2+3i 30 c2.display(); //输出2+3i 31 return 0; 32 }
8
► 2.
前置单目运算符重载为类的成员函数,形式如下: 返回类型 类名::operator op() { …… //this指针对应obj运算对象 }
“op obj” ► 相当于obj.operator op()
► 经过重载后,表达式
9
【例39.2】实现复数类的前置自增运算。
1 #include <iostream> 2 using namespace std; 3 class complex 4 //复数类 { 5 public: 6 complex(double r=0.0,double i=0.0){real=r; imag=i;}//构造函数 7 complex operator ++(); //重载前置++ 8 void display() 9 { 10 cout<<real<<"+"<<imag<<"i"<<endl; 11 } 12 private: 13 double real; //实部 14 double imag; //虚部 15 };
7
► 重载运算符的规则 ► (1)C++绝大部分的运算符可以重载,不能重载的运算符有:
. .* :: ?: sizeof ► (2)不能改变运算符的优先级、结合型和运算对象数目。 ► (3)运算符重载函数不能使用默认参数。 ► (4)重载运算符必须具有一个类对象(或类对象的引用)的参数, 不能全部是C++的内置数据类型。 ► (5)一般若运算结果作为左值则返回类型为引用类型;若运算结 果要作为右值,则返回对象。 ► (6)重载运算符的功能应该与原来的功能一致。
6
► 将‘+’用于复数类的加法运算,运算符函数原型可以是:
complex operator+(const complex &a,const complex &b);
► 调用运算符函数的形式如下:
operator 运算符号(实参列表);
► 例如:complex