第4章 运算符重载
运算符重载的规则

运算符重载的规则运算符重载是C++中一种强大的特性,它允许我们使用现有的运算符进行不同类型的操作。
运算符重载规则很重要,因为它们确保使用该特性时代码的正确性和可靠性。
本文章将为大家详细介绍C++中运算符重载的规则。
1.运算符重载必须与至少一个类或枚举类型相关联。
这意味着,您不能像重载运算符“+”来增加任意两个变量的值,而需要将其放置在自定义类中。
2.运算符重载通常是作为一个成员函数实现的,但也可以作为全局函数实现。
当作为成员函数进行实现时,第一个参数必须是对象本身,而全局函数的对应参数则更灵活。
3.与其他函数一样,每个重载运算符必须有一个唯一的函数签名。
这意味着,您不能定义两个具有相同函数签名的重载运算符(例如,您不能同时实现运算符“+”和“++”)。
4.调用运算符重载函数的语法与调用运算符本身的语法相同。
例如,如果您已经编写了一个重载运算符“+”,则可以使用它来添加两个对象,并使用以下语法来调用它:obj1+obj2。
5.在重载运算符时,应尽量保持运算符的原始功能。
例如,与重载运算符“+”相关联的类中的对象应该具有通常使用加法运算符时对象具有的行为。
否则,将会导致代码的错误,从而使其不可靠。
6.可以重载以下运算符:+,-,*,/,%,^,&,|,~,!,=,<,>,++,--,<<,>>,&&,||,==,!=,<=和>=。
7.如果您在自定义类中定义了运算符重载函数,则应该考虑所有涉及该类的场景,包括复制构造函数、析构函数和其他默认函数。
8.当您在自定义类中实现运算符重载时,应注意函数的返回类型。
如果重载运算符“+”,则返回的结果应该是一个新的对象,而不是直接修改现有对象的值。
总之,正确使用运算符重载规则是确保代码正确性和可靠性的关键因素。
这些规则有助于保持代码的一致性、可读性和可维护性,并有助于提高生产率和代码重用性。
因此,当您在编写代码时使用运算符重载时,请始终牢记这些规则,以确保代码的正确完成和可靠性。
第04章 运算符重载

class A { int i; public: A(int a=0){ i=a;} void Show(void) {cout<<"i="<<i<<endl;} void AddA(A &a, A &b) // 利用函数进行类之间的运算 { i=a.i+b.i; } A operator +(A &a) // 重载运算符+ { A t; t.i=i+a.i; return t; } }; void main(void) { A a1(10),a2(20),a3; 相当于a3=a1.operator+(a2) a1.Show (); a2.Show (); a3=a1+a2; //重新解释了加法,可以直接进行类的运算 a3.AddA(a1,a2); //调用专门的功能函数 a3.Show (); }
总结:
重新定义运算符,由左操作符
调用右操作符。最后将函数返
回值赋给运算结果的对象。
由对象c1调用
若已有运算载Complex operator+ (Complex &c1, Complex &c2) ,那下面的表达式还 合法吗 c3=c2+12; // 这个表达式合法吗? int i=3+5; //这个表达式合法吗?
C++与面向对象程序设计第四章 运算符重载 (PPT4)

有:函数重载;
运算符重; 运算符重载——同一个运算符可以有多种含义或功能。
4.1 运算符重载的语法规则
函数返回值类型 operator 被重载的运算符(函数参数表)
说明:运算符进行重载本质——是编写运算符重载函数; 函数名——必须以operator开始,后跟被重载的运算符;
Байду номын сангаас
注意几点: 1.只能重载C++中已有的运算符。 2.“.”、“.*”、“::”、“?:”和sizeof这5个运算符不允许被 重载。除此之外,都可以被重载。 3.不能改变运算符的操作数个数。比如,对于单目运算符,它只能 有一个操作数。 4.不能改变运算符原有的优先级。 5.不能改变运算符原有的结合性。 6.不能改变运算符对C++内部那些预定义数据类型的操作方式。
C++与面向对象程序设计
第四章:运算符重载
本章教学内容
运算符重载的语法规则 复数类的运算符重载 (+) 字符串类的运算符重载 (+,=,[]) 运算符“<<”的重载 (复数,字符串对象输出 ) 类型转换函数(C++内部数据类型--->类对象)
第四章 运算符重载
“重载”技术是面向对象程序设计的主要特征之一。
//成员函数的实现CComplex.cpp CComplex::CComplex() //默认构造函数 { m_ Re =0.0; m_ Im =0.0; } CComplex::CComplex(double x,double y) //构造函数 { m_ Re=x; m_ Im=y; } CComplex CComplex::operator +(const CComplex c) //两个复数相加 { return CComplex (m_ Re + c.m_ Re, m_ Im+c.m_ Im); } CComplex CComplex::operator +(const double c) //一个复数加一个double数 { return CComplex ( m_ Re +c , m_ Im); }
第4讲 运算符重载(上)

重载函数作为类的友元函数
11
小结
C++规定,有的运算符(如赋值运算符、下标运算符、 C++规定,有的运算符(如赋值运算符、下标运算符、函数 规定 调用运算符)必须定义为类的成员函数, 调用运算符)必须定义为类的成员函数,有的运算符则不能 定义为类的成员函数(如流插入“<<” 定义为类的成员函数(如流插入“<<”和流提取运算符 >>” 类型转换运算符) “>>”、类型转换运算符) 一般将单目运算符重载为成员函数, 一般将单目运算符重载为成员函数,将双目运算符重载为 友元函数 说明: 有的C++编译系统( C++编译系统 6.0)没有完全实 说明: 有的C++编译系统(如Visual C++ 6.0)没有完全实 C++标准 它所提供不带后缀. 标准, 现C++标准,它所提供不带后缀.h的头文件不支持把成员函 数重载为友元函数。但是Visual C++所提供的老形式的带 数重载为友元函数。但是Visual C++所提供的老形式的带 后缀. 后缀.h的头文件可以支持此项功能
第4讲 运算符重载
4.1 运算符重载概念 4.2 重载运算符的规则
1
4.1 运算符重载概念
重载概念:用户根据自己需要对C++已提供的运算符 或函数的功能重新赋予新的含义,使之“一词多义”
函数重载:同一函数名可以实现不同的功能 运算符重载:同一运算符能实现不同的运算操作
2
生活中的重载概念
“杯具”一词重 杯具” 载
12
本讲重点
重载的概念:“双肩挑” 重载的方法: 重载的方法:运算符重载是通过定义函 数实现的 重载的规则:7+1
vc 04 运算符重载

于是: 于是:
string x,y; x=x+y; //表示串 和串 合并,放入串 表示串x 表示串 和串y 合并,放入串x
这就使对基本类型的预定义运算符" 的含义在串类中被扩展 这就使对基本类型的预定义运算符"+"的含义在串类中被扩展 为对串类对象的合并操作,即运算符"+"被重载. 为对串类对象的合并操作,即运算符" 被重载. 被重载 运算符重载应注意的几个问题: 运算符重载应注意的几个问题: 1,哪些运算符可以重载? 哪些运算符可以重载? 中除了下面四种运算符外, 在C++ 中除了下面四种运算符外,系统预定义的运算符都 能被重载. 能被重载.
string x,y;
那么, 实现两个串的合并. 那么,可以使用函数strcat(x,y)实现两个串的合并. 如果在表示字符串的类对象x, 的特定环境下,运算符" 使 如果在表示字符串的类对象 ,y 的特定环境下,运算符"+"使 用于类对象,能被解释为串对象x 的合并, 用于类对象,能被解释为串对象 和y 的合并,则编程就更方便 了.
例如:下边是运算符重载的另一个例子,程序实现了复数的加 例如:下边是运算符重载的另一个例子, 和减运算. 和减运算.
#include <iostream.h> class Complex { public: Complex() { real=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; };
4第四章 运算符重载

const complex operator - (const complex &c) const; void display(); //输出复数 private: //私有数据成员 1.是为了堵塞a+b=c的漏洞。 double real; //复数实部 2. 3.是为了扩大适应性。 double imag; //复数虚部 };
17
[ ]运算符重载为成员函数
下标运算符[]可以重载: 重载形式为:operator[](int); 当 X x; 隐含调用。 x[y] 可被解释为: 显式调用。 x. operator [ ](y); 只能重载为成员函数,不能使用友元函数。 这个类显然是个‚数组类‛。
18
前置++和后置++重载为成员函数
9
使用
void main(){
complex c1(5,4),c2(2,10),c3; //三个复数类的对象 cout<<"c1="; cout<<"c2="; c1.display(); c2.display();
c3=c1-c2; //使用重载运算符完成复数减法 cout<<"c3=c1-c2="; c3.display(); 程序输出结果为:
这三个运算符是许多 教课书没有提到的。
唯一的一个三目运 算符不能重载。
3
运算符重载的基础
设计运算符重载函数,首先要了解运算符原本的运算语义。重
载函数要忠实遵守该运算符作用于基本数据类型时的语义,
并表现出自身所特有的性质。 例如:+ 、+= 、=、++(前)、++(后) ....
简述运算符重载的规则。

简述运算符重载的规则。
运算符重载是指可以为自定义的类类型或枚举类型定义新的含义和功能。
在
C++中,运算符重载遵循以下一般规则:
1. 运算符重载必须至少有一个操作数是用户自定义的类类型或枚举类型的对象,否则将无法重载。
2. 运算符重载可以作为成员函数或非成员函数来实现。
3. 对于成员函数的运算符重载,操作数的数量为运算符的操作数减去1。
例如,重载双目运算符时(如+、-、*等),成员函数需要接受一个参数,用于表示另一个操作数。
4. 对于非成员函数的运算符重载,所有操作数都作为参数传递给函数。
可以通过将重载运算符函数声明为友元函数来访问类的私有成员。
5. 对于重载一元运算符(如++、),如果是成员函数,则返回一个修改后的对象;如果是非成员函数,则返回一个新的对象。
6. 对于重载二元运算符(如+、-、*等),如果是成员函数,则一个对象被修改,另一个对象不变;如果是非成员函数,则返回一个新的对象。
7. 运算符重载不能改变原有运算符的优先顺序和结合性。
8. 运算符重载遵循函数重载的规则,即可以根据参数类型和参数数量进行重载,实现不同的功能。
需要注意的是,运算符重载应该遵循语义上的合理性并不滥用。
第4章 运算符重载

• 在C++中只能重载单目运算符、双目运算符及 不确定目数运算符“()”
下列运算符不能重载 . 类成员运算符 .* 成员指针运算符 :: 域解析运算符 ?: 条件表达式运算符 “#” (???) sizeof(???)
重载运算符有哪些限制?
(1) 不可臆造新的运算符。必须把重载运算符 限制在C++语言中已有的运算符范围内的允许 重载的运算符之中。 (2) 重载运算符坚持4个“不能改变”。 · 不能改变运算符操作数的个数; · 不能改变运算符原有的优先级; · 不能改变运算符原有的结合性; · 不能改变运算符原有的语法结构
用类的成员函数重载双目运算符
• 双目运算符重载为类的成员函数时,形参 表中有一个参数,以当前对象作为运算符 的左操作数,参数作为右操作数。
例4.4 双目运算符重载为类的成员函数示例。 // 声明整型类 class Integer { private: // 数据成员 int num; // 数据值 public: // 公有函数 Integer(int n = 0): num(n){ } // 构造函数 void Set(int n) { num = n; } // 设置数据值 int Get() const { return num; } // 返回数据值 Integer operator+(const Integer &a) const// 重载加法运算符“+” { return Integer(this->num + a.num); } }; int main() // 主函数main() { Integer i(6), j(9), k; // 定义整型对象 k = i + j; // 对整型对象求加法运算,i+j等价于i.operator+(j); cout<<i.Get()<<"+"<<j.Get()<<"="<<k.Get()<<endl;// 输出数值 system("PAUSE"); // 输出系统提示信息 程序运行时屏幕输出如下: return 0; // 返回值0, 返回操作系统 6+9=15 } 请按任意键继续. . .
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Overloadable operators
+ <<= >>= ~ &=
delete
* == ^=
/ != |=
= <= &&
< >= ||
> ++ %=
+= -[]
-= % ()
*= & ,
/= << ^ ! ->* ->
>> | new
new[]
delete[]
例1 :复数的+、-、=运算 (5/5)
x.print(); cout << " = "; y.print(); cout << " + "; z.print(); x = y - z; cout << "\n\nx = y - z:\n"; x.print(); cout << " = "; y.print(); cout << " - "; z.print(); cout << '\n'; return 0;
程序执行结果:
s1 is NULL! s2 is not NULL!
4.3 单目运算符重载 (2/3)
特殊的单目运算符++、-以++ 为例( -- 同理) ,设b为类C的对象 前自增,++b
重载函数可为C的成员函数,原型为 C & operator++(); 也可为C的友元函数,原型为 C & operator++(C &);
例1 :复数的+、-、=运算 (3/5)
Complex Complex::operator-(const Complex &operand2) const { Complex diff; diff.real = real - operand2.real; diff.imaginary=imaginary - operand2.imaginary; return diff; } Complex& Complex::operator=(const Complex &right) { real = right.real; imaginary = right.imaginary; return *this; // enables concatenation } void Complex::print() const { cout<<'('<<real<< ", " << imaginary << ')'; }
例3:定义字符串类String,并以友元函数的方式重载运 算符 ! 以判断对象中的字符串是否为空串 (2/3)
//文件String.cpp #include <cstring> #include "string.h" String::String(char *m) { str = new char[strlen(m)+1]; strcpy(str,m); } String::~String() { delete [] str; } bool operator!(String &s)//友元函数实现运算符重载 { if (strlen(s.str) == 0) return true; return false; }
4.2 重载运算符的方式 (2/2)
如果双目运算符的左操作数不是本自定 义类的对象,重载运算符的函数必须定 义为友元函数
<<、>> 运算符可交换性的实现(一个操作数是自定 义类的对象,另一个操作数是基本类型)
运算符重载函数的定义要保证运算无二 义性
4.3 单目运算符重载 (1/3)
4.3 单目运算符重载 (3/3)
后自增,b++
重载函数可为C的成员函数,原型为 C operator++(int); 系统自动将b++转换为函数调用b.operator++(0) 重载函数也可为C的友元函数,原型为 C operator++(C &, int); 系统自动将b++转换为函数调用operator++(b,0)
例2:定义字符串类String,并以成员函数的方式重载运 算符 ! 以判断对象中的字符串是否为空串 (3/3)
//文件ex4_2.cpp #include <iostream> #include "string.h" using namespace std; int main() { String s1, s2("some string"); if (!s1) //!s1等价于s1.operator!() cout<<"s1 is NULL!"<<endl; else cout<<"s1 is not NULL!"<<endl; if (!s2) cout<<"s2 is NULL!"<<endl; else cout<<"s2 is not NULL!"<<endl; return 0; }
例1 :复数的+、-、=运算 (4/5)
//文件3: 4_1.cpp--主函数定义 #include "complex.h" #include <iostream> using namespace std; int main() { Complex x, y(4.3, 8.2), z(3.3, 1.1); cout << "x: "; x.print(); cout << "\ny: "; y.print(); cout << "\nz: "; z.print(); x = y + z; cout << "\n\nx = y + z:\n";
例1 :复数的+、-、=运算 (2/5)
//文件2:complex.cpp--复数类的成员函数定义 #include "complex.h" #include <iostream> using namespace std; Complex::Complex(double r, double i) { real = r; imaginary = i; } Complex Complex::operator+(const Complex &operand2) const { Complex sum; sum.real = real + operand2.real; sum.imaginary=imaginary + operand2.imaginary; return sum; }
例2:定义字符串类String,并以成员函数的方式重载运 算符 ! 以判断对象中的字符串是否为空串 (2/3) //文件string.cpp #include <cstring> #include "string.h" String::String(char *m) { str = new char[strlen(m)+1]; strcpy(str,m); } String::~String() { delete [] str; } bool String::operator!() //成员函数实现运算符重载数 { if (strlen(str) == 0) return true; return false; }
操作数是自定义类的对象或对象的引用 作为成员函数重载
没有参数
作为友元函数重载
1个参数,参数为自定义类的对象或对象的 引用
例2:定义字符串类String,并以成员函数的方式重载运 算符 ! 以判断对象中的字符串是否为空串 (1/3)
//文件string.h #if !defined __STRING__H__ #define __STRING__H__ class String { public: String(char *m=""); //使用默认参数的构造函数 ~String(); //定义运算符重载成员函数原型 bool operator!(); private: char *str; }; #endif
例4:定义数值类Number,并以友元函数 的方式重载运算符 ++ (1/4)
//number.h #if !defined _NUMBER_H_ #define _NUMBER_H_ class Number { private: int num; public: Number(int n = 0); int getNum(); friend Number& operator ++(Number&);//++运算符重载函数(前 自增) friend Number operator ++(Number&, int);//++运算符重载函数 (后自增) }; #endif
例1 :复数的+、-、=运算 (1/5)
// 文件1:complex.h--复数类的定义 #ifndef COMPLEX_H #define COMPLEX_H class Complex { public: Complex(double = 0.0, double = 0.0); Complex operator+(const Complex&) const; Complex operator-(const Complex&) const; Complex& operator=(const Complex&); void print() const; private: double real; // real part double imaginary; // imaginary part }; #endif