第九章 运算符重载
oop_9
9.2 运算符函数参数
A A::operator++(int){ return A (a++); } void main(void){ A a(5); //后置++,返回对象(右值) //后置++,先取值构造,后运算
cout<<"a.a="<<(--a).get( )<<"\n"; cout<<"a.a="<<(++a).get( )<<"\n";
7
9.1 概述
运算符=、–>、( )和[ ]不能重载为普通函数,没 有普通函数也就不能定义普通友元:
int operator=(int, A); int operator( )(A, int); int operator[ ](A, int); class A{ friend int operator=(int,A); friend int operator()(A,int); friend int operator[](A,int); friend int operator += (int,A); }; //错误,不能重载为普通函数 //错误,不能重载为普通函数 //错误,不能重载为普通函数 //错误,不能定义为普通友元 //错误,不能定义为普通友元 //错误,不能定义为普通友元 //正确
纯单目运算符,只能有一个操作数,包括: !、~、sizeof、new、delete 等 纯双目运算符,只能有两个操作数,包括: [ ]、->、%、= 等 三目运算符,有三个操作数,包括: ?: 既是单目又是双目的运算符,包括: +、-、&、* 等
C++教学 第9章+友元函数与运算符重载
float v1(A &a) { return PI*a.r*a.r*a.h;} //友元函数volum在类体外定义 float v3(A b) //普通函数 { return PI*b.getr()*b.getr()*b.geth();} void main() { A a1(25,40); A a2(25,40); cout<<v1(a1)<<"\n"; //友元函数的调用 cout <<a2.v2( )<<"\n"; cout<<v3(a1); }
对于大多数程序设计语言,运算符的定义由编译器给出,且 这种用法是不允许用户改变的。在C++中,允许用户重新定 义已有的运算符,并按规定要求去完成特定的操作。 使用成员函数或友元函数,通过操作对象成员,从而实现对 象参加运算的目的。
10
运算符重载函数的定义格式如下: (1)运算符重载函数定义为类的成员函数 函数类型 operator 运算符 (参数表) { …… }
15
9.3 一元运算符重载 C++中允许重载的一元运算符有: 自增运算符“++”、自减运算符“--”、 负号运算符“-”、逻辑非运算符“!”等。
16
9.3.1 用成员函数重载一元运算符
用成员函数重载“++”运算符的格式为: (1)++为前缀形式 函数类型 operator++(void) { 函数体 } (2)++为后缀形式 函数类型 operator++(int) { 函数体 } 重载自减运算符“--”的格式与重载“++”运算符类似。
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运算符重载其实就是定义⼀个函数,在函数体内实现想要的功能,当⽤到该运算符时,编译器会⾃动调⽤这个函数,它本质上是函数重载。
第9讲 运算符重载(二)。
面向对象程序设计-多态性
赋值运算符“=”的重载
对任一类X,如果没有用户自定义的赋值运算符 函数,那么系统自动地为其生成一个缺省的赋值 运算符函数,定义为类X中的成员到成员的赋值, 例如:
X &X::operator=(const X& source)
{ //…成员间赋值 }
面向对象程序设计-多态性
函数名பைடு நூலகம்
面向对象程序设计-多态性
运算符重载为友元
2.单目运算 1)前置单目运算:U oprd 对于前置单目运算符 U,如“-”(负号)等, 如果要实现表达式U oprd(其中oprd为A类的对 象),则U可以重载为A类的友元函数,函数的 形参为 A 类的对象。经过重载之后,表达式 U oprd相当于函数调用operator U (oprd)。
面向对象程序设计-多态性
运算符重载
④运算符new和delete重载。 通过重载new和delete,可以克服new和 delete的不足,使其按要求完成对内存的管理。 ⑤逗号运算符“,”重载。 逗号运算符构成的表达式为“左操作数, 右操作数”,该表达式返回右操作数的值。
面向对象程序设计-多态性
流运算符的重载
面向对象程序设计-多态性
赋值运算符“=”的重载
public: string(char *s) {ptr=new char[strlen(s)+1]; strcpy(ptr,s); } ~string() { delete ptr; } void print()
{ cout<<ptr<<endl; }
面向对象程序设计-多态性
流运算符的重载
ostream&operator<<(ostream &out,complex &a) { out<<" ("<<a.real<<", "<<a.imag<<"i) "; return out; }
运算符重载(面向对象程序设计C++)
运算符重载运算符重载的本质是函数重载,它也是C++多态的一种体现,为用户提供了一个直观的接口,调用运算符操作自定义数据类型其实就是调用运算符函数。
运算符重载增强了C++的可扩充性,使得C++代码更加直观、易读,且便于对对象进行各种运算操作。
重载的运算符是具有特殊名字的函数:它们的名字由关键字operator 和其后要重载的运算符共同组成。
语法格式 返回类型 operator 运算符(参数列表){函数体; }运算符重载规则:只能重载C++中已有的运算符,不能创建新的运算符。
重载之后的运算符不能改变其优先级和结合性,也不能改变其操作数的个数及语法结构。
避免没有目的地使用重载运算符。
类属关系运算符“.”、成员指针运算符“*”、作用域运算符“::”、sizeof 运算符和三目运算符“?:”不可以重载。
输入输出运算符的重载 IO 标准库使用“>>”和“<<”运算符执行输入输出操作,对于这两个运算符来说,IO 库定义了其基本数据类型的操作,但若要直接对类对象进行输入输出,则需要在类中重载这两个运算符。
输入运算符语法格式istream& operator>>(istream&, 类对象引用);输出运算符语法格式ostream& operator<<(ostream&,const 类对象引用); 关系运算符的设计准则关系运算符都要成对的重载。
“==”运算符应该具有传递性当成对出现运算符重载时,可以把一个运算符的工作委托给另一个运算符。
赋值运算符的重载对于赋值运算符来说,如果不重载,那么类会自动为我们提供一个赋值运算符。
这个默认的赋值运算符跟默认拷贝构造函数一样,就是把一个对象的数据成员的值复制给另一个对象对应的数据成员。
下标运算符的重载返回类型 operator[] (参数列表);重载“[]”运算符可以实现两个目的:(1)“对象[下标]”的形式类似于“数组[下标]”,更加符合习惯。
运算符重载函数的两种主要方式
运算符重载函数的两种主要方式
运算符重载是C++语言中的一种特性,它可以让用户定义类或结构体中的运算符的行为,以满足用户的需求。
换句话说,运算符重载就是在类或结构体中定义新的运算符,以替代原有的运算符。
一般来说,运算符重载通过两种主要方式实现:类内重载和类外重载。
类内重载是将运算符重载函数定义在类内部,该函数的声明必须使用operator关键字。
这种方式的优点是可以使用类的受保护成员。
类内重载的运算符函数有一个或两个参数,参数的类型是类的类型,或者是类的对象。
类外重载是在类外定义运算符重载函数,该函数的声明仍然要使用operator关键字,但参数的类型是左操作数和右操作数的类型。
类外重载的运算符函数有两个参数,参数的类型是左操作数和右操作数的类型。
类外重载的优点是可以使用不同类型的操作数,而类内重载的运算符函数只能使用类的类型或类的对象作为参数。
使用运算符重载有很多优点,可以提高程序的可读性,使代码更加容易理解。
此外,运算符重载还可以减少代码量,减少函数调用的次数,以及提高程序的效率。
总之,运算符重载是一种有效的编程技巧,可以提高程序的可读性,提高程序的效率,增加程序的可维护性,减少代码量。
使用运算符重载,可以使用户能够更加熟练地使用C++语言,也可以更好地保护类的封装性。
运算符重载
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. 逻辑运算符重载逻辑运算符包括条件运算符和逻辑非运算符。
每个逻辑运算符都有一组默认的行为,可以通过运算符重载来自定义它们的行为。
OOP(C++)_第9章_运算符重载(最终版)
《面向对象程序设计》 中国科学技术大学计算机系 马建辉
5
9.2 运算符重载的语法
《面向对象程序设计》 中国科学技术大学计算机系 马建辉
6
9.2.1 语法
函数返回值 类名 保留字 形式参数 被重载的运 算符
type classname::operator@(arg_list)
函数返回值 保留字 被重载的运形式参数 算符
《面向对象程序设计》 中国科学技术大学计算机系 马建辉 22
void main( ){ X x1(10); int i=x1+x2; // 二义性 i=12+x1; //二义性 二义性 }
《面向对象程序设计》 中国科学技术大学计算机系 马建辉
23
11
实现/ 例3:复数相“加”(重载“+”实现/外部函数) 复数相“ 重载“ 实现 外部函数) class Complex{ private: double rpart; double ipart; public: Complex(){ rpart=ipart=0.0; } Complex(double rp,double ip){ rpart=rp; ipart=ip; } friend Complex Operator+( const Complex & com1, const Complex &com2 ); };
class Complex{ private: double rpart; double ipart; public: Complex(){ rpart=ipart=0.0; } Complex(double rp,double ip){ rpart=rp; ipart=ip; Complex Operator+(const Complex & com){ Complex temp; temp.rpart = com.rpart+rpart; temp.ipart = com.ipart+ipart; return temp; } };
第9章 运算符重载、模板
Email:zhuoyueming@
三、函数模板 函数模板
模板是函数或类的通用样板,当函数或类需要处理多种类型的数据,并且其 处理方法一样时,可以将其定义为模板。模板分为函数模板和类模板。 函数模板的一般说明形式如下: template <模板形参表> <返回值类型> <函数名> (模板函数形参表) { //函数定义体 } 其中,<模板形参表>可以包含基本数据类型,也可以包含类类型。类型形参 需要加前缀class 或 tpyename,如果类型形参多于一个,则每个类型形参都 要使用class 或 typename。 函数模板只是说明,不能直接执行,需要实例化为模板函数后才能执行。 当编译系统发现有一个函数调用<函数名>(<实参表>);时,将根据<实参表>中 的类型生成一个重载函数即模板函数,该模板函数的定义体与函数模板的函 数定义体相同,而<形参表>的类型则以<参数表>的实际类型为依据。 Email:zhuoyueming@
Email:zhuoyueming@
难点剖析
若重载为类的成员函数,如: class Fraction { private: ...... public: Fraction operator+(const Fraction f2) { Fraction f; f.nume=nume*f2.deno+f2.nume*deno; f.deno=deno*f2.deno; return f; } }; • 则上面的语句3+f1将出错,因为不能解释为3.operator(f1). Email:zhuoyueming@
一、运算符重载的基本方法
运算符重载——精选推荐
运算符重载运算符重载学习运算符重载,让运算符能做⼀些原来做不了的事情,⽅便它的使⽤⼀、运算符重载的概念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)不能返回局部变量的引⽤。
第9讲 运算符重载.
2.运算符重载的方法
int main( ) { Complex c1(3,4),c2(5,-10),c3; c3=c1+c2; //运算符+用于复数运算 cout<<″c1=″;c1.display( ); cout<<″c2=″;c2.display( ); cout<<″c1+c2=″;c3.display( ); return 0; 运行结果如下: } c1=(3+4i) c2=(5-10i) c1+c2=(8,-6i)
重载运算符的函数格式: 函数类型 operator 运算符名称 (形参表列) { 对运算符的重载处理 }
2019年2月1日8时44分 9
2.运算符重载的方法
例2 改写例1,重载运算符“+”,使之能用于两个复数相加。 #include <iostream> using namespace std; class Complex {public: Complex( ){real=0;imag=0;} Complex(double r,double i){real=r;imag=i;} Complex operator+(Complex &c2); //声明重载运算符的函数 void display( ); private: double real; double imag; };
C++面向对象程序设计
湖南工业大学 计算机与通信学院
2019年2月1日8时44分 1
第9讲 运算符重载
9.1 授课内容 运算符重载。主要内容有: 1.运算符重载的含义、方法和规则; 2.运算符重载函数作为类的成员函数和友元函数; 3.重载流运算符;
C++学习之运算符重载的总结
C++学习之运算符重载的总结C++学习之运算符重载的总结运算符重载是对已有的运算符赋予多重含义,使同⼀个运算符作⽤域不同类型的数据导致不同⾏为的发⽣,C++为运算符重载提供了⼀种⽅法,即运算符重载函数。
其函数名字规定为operator后紧跟重载运算符。
⽐如:operator+(),operator*()等。
(1)运算符重载函数作为类的友元函数的形式: class 类名 { friend 返回类型 operator运算符(形参表); } 类外定义格式: 返回类型 operator运算符(参数表) { 函数体 }友元函数重载双⽬运算符(有两个操作数,通常在运算符的左右两则),参数表中的个数为两个。
若是重载单⽬运算符(只有⼀个操作数),则参数表中只有⼀参数。
同⼀个运算符可以定义多个运算符重载函数来进⾏不同的操作。
(2)运算符重载函数作为类的成员函数的形式: class 类名 { 返回类型 operator 运算符(形参表); } 类外定义格式: 返回类型类名:: operator 运算符(形参表) { 函数体; }对于成员函数重载运算符⽽⾔,双⽬运算符的参数表中仅有⼀个参数,⽽单⽬则⽆参数。
同样的是重载,为什么和友元函数在参数的个数上会有所区别的。
原因在于友元函数,没有this指针。
对于双⽬运算符⽽⾔,运算符重载函数的形参中仅为⼀个参数,它作为运算符的右操作数(如com2对象),⽽当前对象作为左操作数(如:上述中的com1对象),它是通过this指针隐含传递给成员运算符重载函数的。
例如下⾯这样的定义:Complex operator+(Complex com1);//成员函数重载双⽬运算符+20Complex Complex::operator+(Complexcom1)21{22return Complex(real+com1.real,imag+com1.imag);23}对于单⽬运算符⽽⾔,当前对象作为运算符的操作数。
运算符重载解读
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)运算符重载可以通过成员函数的形式,也可是通过友元函数,⾮成员⾮友元的普通函数。
第9章-运算符重载
8
§9-3 实例
9.3.3 重载增量运算符
返回引用 前缀与后缀
参数传递用引用. 参数传递用引用. 后缀时,参数增加1 后缀时,参数增加1,临时变量存放原 变量值作为返回. 变量值作为返回.
9
§9-3 实例
9.3.4 转换运算符
格式: 转换类型(); 格式:operator 转换类型(); 功能:将对象转换成某类型(强制类型转换) 功能:将对象转换成某类型(强制类型转换) #include <iostream.h> class RMB { public: RMB(double value=0.0); operator double() { return yuan+jf/100.0; } void display() { cout<<(yuan+jf/100.0)<<endl; } protected: unsigned int yuan; unsigned int jf; };
面向对象程序设计(C++) 面向对象程序设计(C++)
Oriented Object Programming (C++)
第九章 运算符重载
主讲: 主讲:宋丽红
第九章 运算符重载
§9-1 使用运算符重载的必要性 §9-2 重载运算符 §9-3 实例
2
§9-1 使用运算符重载的必要性
9.1 使用运算符重载的必要性
10
§9-3 实例
RMB::RMB(double value) { yuan =value; jf=(valuejf=(value-yuan)*100+0.5; } void main() { RMB d1(2.0), d2(1.5),d3,d4; //显式转换 d3=RMB((double)d1+(double)d2); //显式转换 //隐式转换 d4=d1+d2; //隐式转换 d3.display(); d4.display(); }
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
运算符从本质上是代表了一种运算操 作,所以C++中的运算符重载采用的是函 数的形式。 又因为运算符牵扯到参与运算的运算 量的个数、位置、顺序以及优先级,而 这些又不是C++中普通的函数定义能解决 的,所以要依靠编译器在内部解决。再 加上可识别的问题,导致了运算符的重 载不能是任意的。
C++中只能重载已有运算符中的一部 分,不能创新。 当运算量都是基本类型是不能重载。 (不可识别) . :: * -> ? :不能重载(不可识别)
第九章 运算符重载
严格说C语言中就有运算符重载 如:+ 运算符对int型数据的操作与对 float型数据的操作内涵不同,但表示相 同。
C++中的运算符重载首先是在逻辑 体系上解决了user define type 与内嵌类 型( 如:int )地位相同,但无匹配的 运算符的问题。 其次,运算符重载使程序设计中对 象的操作(如:Carray的[ ])与对象的 运算(如:+ ,- ,* ,/等 )更直观、 更简单,并且可以充分发挥C++中的表 达式的作用。
如何重载运算符 在C++中运算符的重载,可以是非成员函 数也可以是成员函数(少一个this)。 见程序。 值得注意的是,重载的运算符从本质上讲 是函数,运算符的意义取决于函数的定义,受 程序员控制,由程序员决定。定义的内涵可以 与重载的运算符的公认含义完全不同,(如: 重载的 + 运算符,其定义可以是相乘的意 思),这很容易导致程序思路的混乱。应尽量 避免。