第五讲第五讲运算符重载运算符重载(2)
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运算符重载其实就是定义⼀个函数,在函数体内实现想要的功能,当⽤到该运算符时,编译器会⾃动调⽤这个函数,它本质上是函数重载。
运算符重载
void complex::print( ) { if (imag==0) cout<<real<<endl; else if(imag>0) cout<<real<<"+"<<imag<<"i\n"; else cout<<real<<imag<<"i\n"; } complex operator -(complex obj) { complex temp; temp. real= -obj.real ; temp. imag= -obj.imag; return temp; }
10
void main( ) { complex com1(2.3,4.6),com2(3.6,2.8),result; cout<<"complex com1 and com2 orderly:\n"; com1.print( ); com2.print( ); result=com1+com2; cout<<"com1+com2="; result.print( ); result=com1-com2; cout<<"com1-com2="; result.print( ); result=com1*com2; cout<<"com1*com2="; result.print( ); result=com1/com2; cout<<"com1/com2="; result.print( ); }
2、双目运算符的重载
运算符重载
第4章运算符重载4.1 什么是运算符重载所谓重载,就是重新赋予新的含义。
函数重载就是对一个已有的函数赋予新的含义,使之实现新功能。
运算符也可以重载。
实际上,我们已经在不知不觉之中使用了运算符重载。
如:+可以对int、float、double的数据进行加法运算。
现在要讨论的问题是:用户能否根据自己的需要对C++已提供的运算符进行重载,赋予它们新的含义,使之一名多用。
譬如,能否用“+”号进行两个复数、两个点的相加。
在C++中不能在程序中直接用运算符“+”对复数进行相加运算。
用户必须自己设法实现复数相加。
例如用户可以通过定义一个专门的函数来实现复数相加。
见下例。
//例4.1 通过函数来实现复数相加。
#include <iostream>using namespace std;class Complex{public:Complex(){real=0;imag=0;} //构造函数Complex(double r,double i){real=r;imag=i;} //构造函数重载Complex complex_add(Complex &c2); //声明复数相加的函数void display(); //声明输出函数private:double real, imag;};Complex Complex::complex_add(Complex &c2){ Complex c;c.real=real+c2.real;c.imag=imag+c2.imag;return c;//以上可简写为:return Complex(real+c2.real,imag+c2.imag);}void Complex::display(){ cout<<"("<<real<<","<<imag<<"i)"<<endl;}int main(){ Complex c1(3,4),c2(5,-10),c3;c3=plex_add(c2);cout<<"c1="; c1.display();cout<<"c2="; c2.display();cout<<"c1+c2="; c3.display();return 0;}结果无疑是正确的,但调用方式不直观、太烦琐,使人感到很不方便。
C++运算符重载讲解与经典实例 (2)
5.重载运算符有哪些限制:
(1)不可臆造新的运算符。必须把重载运算符限制在C++语言中已有的运算符范围内的允许重载的运算符之中。
(c1+c2)*(c1-c2)*c2/c1=9.61538+25.2308i
在程序中,类complex定义了4个成员函数作为运算符重载函数。将运算符重载函数说明为类的成员函数格式如下:
<类名>operator<运算符>(<参数表>)
其中,operator是定义运算符重载函数的关键字。
程序中出现的表达式:
位操作运算符:&,|,~,^,<<,>>
逻辑运算符:!,&&,||;
比较运算符:<,>,>=,<=,==,!=;
赋值运算符:=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=;
其他运算符:[],(),->,,(逗号运算符),new,delete,new[],delete[],->*。
double real;
double imag;
};
complex a(10,20),b(5,8);
“a+b”运算如何实现?这时候我们需要自己编写程序来说明“+”在作用于complex类对象时,该实现什么样的功能,这就是运算符重载。运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据导致不同类型的行为。
运算符重载形式有两种,重载为类的成员函数和重载为类的友元函数。
运算符重载为类的成员函数的一般语法形式为:
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; ▪}
运算符重载的方法
运算符重载的方法
运算符重载是指在类中重新定义某个运算符,使其能够用于类的实例。
重载运算符可以方便地对类对象进行加、减、乘、除等基本运算,也可以定义自定义运算符,以实现类特定的功能。
运算符重载的方法如下:
1.编写运算符重载函数:将要重载的运算符的符号作为函数名,如“+”、“-”、“*”、“/”等,对于自定义运算符可以自己命名。
2.指定参数个数和类型:重载函数需要参数,这些参数有不同的类型,可以是类的成员变量或其他类型的变量。
3.重载运算符要求:
(1)操作数至少有一个是类的实例,重载函数可以定义为类的成员函数或全局函数。
(2)运算符重载不能改变原有操作数的类型或个数。
(3)运算符重载函数可以返回任何类型的值,甚至可以是类的实例。
4.使用运算符:一旦重载运算符函数定义好之后,就可以像使用普通的运算符一样使用它。
需要注意的是,运算符重载不是万能的,对于某些运算符,如“&&”、“”等,是不能够重载的。
此外,在使用运算符重载时应该避免过于复杂的实现方式,以防止代码难以理解和维护。
5种重载的运算符及其对应的方法
5种重载的运算符及其对应的方法重载运算符是C++语言的一个重要特性,它允许自定义类类型对内置运算符进行操作。
通过重载运算符,可以使得自定义类类型的对象可以像内置类型一样使用运算符。
在C++中,有许多运算符都可以通过重载来定义对应的操作。
本文将介绍5种常见的重载运算符及其对应的方法。
1. 赋值运算符(=)赋值运算符重载函数的原型为:Class& operator=(const Class& other)这个运算符用于将一个对象的值赋给另一个对象,例如:```cppClass obj1;Class obj2;obj2 = obj1; // 调用赋值运算符重载函数```2. 算术运算符(+、-、*、/、%)算术运算符重载函数的原型为:Class operator+(const Class& other)、Class operator-(const Class& other)、Class operator*(const Class& other)、Classoperator/(const Class& other)、Class operator%(const Class& other)这些运算符用于进行对象之间的加减乘除和取模运算,例如:```cppClass obj1;Class obj2;Class obj3;obj3 = obj1 + obj2; // 调用加法运算符重载函数```3. 关系运算符(==、!=、>、<、>=、<=)关系运算符重载函数的原型为:bool operator==(const Class& other)、bool operator!=(const Class& other)、bool operator>(const Class& other)、booloperator<(const Class& other)、bool operator>=(const Class& other)、booloperator<=(const Class& other)这些运算符用于比较两个对象之间的大小和相等关系,返回一个布尔值,例如:```cppClass obj1;Class obj2;if(obj1 == obj2) // 调用等于运算符重载函数{// 两个对象相等}```4. 递增、递减运算符(++、--)递增、递减运算符重载函数的原型为:Class& operator++()、Classoperator++(int)、Class& operator--()、Class operator--(int)这些运算符用于对对象进行递增、递减操作,分为前置和后置形式,例如:```cppClass obj;obj++; // 调用后置递增运算符重载函数```5. 下标运算符([])下标运算符重载函数的原型为:Type& operator[](int index)这个运算符用于对对象进行类似数组的访问操作,例如:```cppClass obj;Type value = obj[index]; // 调用下标运算符重载函数```通过重载运算符,可以使得自定义类类型的对象能够以一种直观、简洁的方式与内置类型进行相似的操作。
运算符重载
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. 逻辑运算符重载逻辑运算符包括条件运算符和逻辑非运算符。
每个逻辑运算符都有一组默认的行为,可以通过运算符重载来自定义它们的行为。
《运算符重载》PPT课件_OK
bool operator>=(const Rational &r1) const;
bool operator!=(const Rational &r1) const;
11
void display() { cout << num << '/' << den; }
}
函数实现
Rational Rational::operator+(const Rational &r1) const { Rational tmp;
4
可以重载的运算符
+-*/%^ ~ ! = < > += /= %= ^= &= |= <<= == != <= >= -- ->* , -> [] () new[] delete[]
& -= << && new
| *= >> >>= || ++
delete
5
不能重载的运算符
. .* :: ?: sizeof
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;
tmp.num = num * r1.den + r1.num * den; tmp.den = den * r1.den; tmp.ReductFraction(); return tmp; }
运算符重载——精选推荐
运算符重载运算符重载学习运算符重载,让运算符能做⼀些原来做不了的事情,⽅便它的使⽤⼀、运算符重载的概念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++学习之路—运算符重载(⼆)运算符重载作为类的成员函数和友元函数对运算符重载的函数有两种处理⽅式:(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类中声明它为友元函数。
运算符重载解读
02
在重载运算符时,应明确指定 运算符的参数类型和返回类型 ,避免与其他操作符混淆。
03
在重载运算符时,应尽量使用 有意义的操作符名称,以提高 代码的可读性。
考虑性能和效率
01
02
03
运算符重载时,应考虑 性能和效率,避免对原 有代码造成不必要的性
能损失。
在重载运算符时,应尽 量减少额外的计算和内 存开销,以提高代码的
一元运算符重载
一元运算符重载是指对一元运算符进行重载,使其能够应用于一个操作数。例如,在C中,我们可以 重载一元减号运算符(-)来返回一个数的相反数。
常见的一元运算符有:+、-、~、!等。
二元运算符重载
二元运算符重载是指对二元运算符进行重载,使其能够应用于两个操作数。例如,在C中,我们可以重载加号运算符(+)来定 义两个自定义类型的相加行为。
01
提高代码可读性
运算符重载可以使代码更易读, 因为运算符的使用可以使代码更 简洁、更直观。
02
03
方便函数调用
运算符重载可以使得函数调用更 加方便,因为运算符的使用可以 减少函数调用的开销。
04
缺点分析
易造成混淆
运算符重载可能会使得代码难以理解,因为 运算符的行为可能会被改变,导致读者难以
理解代码的含义。
常见的二元运算符有:+、-、*、/、%等。
三元运算符重载
三元运算符重载是指对三元运算符进行重载,使其能够应用于三个操作数。例如,在C中,我们可以重载条件运 算符(?)来定义一个自定义类型的条件判断行为。
常见的三元运算符有:?:。
03
运算符重载的常见场景
类与类之间的运算
01
两个类对象之间的加法运算,可以表示它们之间的某种关联或 合并。
C程序设计运算符重载资料
•
{
目的对象与源对象不是同一个对象
•
……
复制被被赋值对象
•
}
•
*;
返回目的对象
•}
*重载赋值运算符“=”
• 如用户没有为一个类重载赋值运算符,编译程序将生成一个默认赋值运算符函数。赋值运算 把源对象的数据成员逐个地复制到目的对象的相应数据成员
0;
返回值0, 返回操作系统
}
程序运行时屏幕输出如下: 6 -6 请按任意键继续. . .
用类的友元函数重载双目运算符
• 将双目运算符重载为类的友元函数时,友元函数形参表中包含有两个参数,这两个参数分别 作为运算符的左、右操作数。
例4.6 双目运算符重载为类的友元函数示例。
<>
编译预处理命令
;
使用命名空间
例4.8 双目运算符重载为普通函数示例。 声明整型类
{
:
数据成员
;
数据值
:
公有函数
( n = 0): (n){ }
构造函数
( n) { = n; }
设置数据值
() { ; } 返回数据值
};
( , ) 重载运算符"+"
{ (() + ()); }
()
主函数()
{
i(6), j(9), k;
定义整型对象
例4.5 单目运算符重载为类的友元函数示例。
<>
编译预处理命令
;
使用命名空间
声明整型类
{
: 数据成员
在 6.0下会出现的编译时错语,是 6.0的一个,在
<> ;;
编译预处理:
:
改为:
运算符重载详解
运算符重载详解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)。
程序设计实习(I): C++程序设计序设计实(I)C序设计第五讲运算符重载(2)主要内容☐两种运算符重载的实现方式☐常见的运算符重载⏹流运算符:>> 、<<⏹自增运算符++、自减运算符--2算符重载☐运算符重载⏹对已有运算符赋予多重的含义⏹使同一运算符作用于不同类型的数据时导致不同类型的行为☐目的⏹扩展C++中提供的运算符的适用范围,以用于类所表示的抽象数据类型同个,同操作,同☐同一个运算符,对不同类型的操作数,所发生的行为不同⏹(5, 10i) + (4, 8i) = (9, 18i)5+49⏹5 + 4 = 93算符重载的实质是函数重载☐运算符重载的实质是函数重载☐在程序编译时:⏹把含运算符的表达式转换成对运算符函数的调用⏹把运算符的操作数转换成运算符函数的参数⏹运算符被多次重载时,根据实参的类型决定调用哪个运算符函数⏹运算符可以被重载成普通函数,也可以被重载成类的成员函数4运算符重载的两种方式☐重载为普通函数时,参数个数为运算符目数x=y+z;//x=y.operator+(z)⏹x y + z; // x y.operator+ (z)重载为成参个为算符☐重载为成员函数时,参数个数为运算符目数减一y;p(y p())⏹x = y + z; // x.operator=(y.operator+(z))5运算符重载的注意事项☐C++不允许定义新的运算符载后算符含应该符合常习惯☐重载后运算符的含义应该符合日常习惯⏹complex_a+ complex_bword a>word b⏹word_a word_b⏹date_b= date_a+ n运算符重载不改变运算符的优先级☐☐以下运算符不能被重载:“.”,“.*”,“::”,“?:”, sizeof☐重载运算符()、[]、->或者赋值运算符=时,运算符重载函数必须声明为类的成员函数6运算符重载为友元一般情况下将运算符重载为是较好的选择☐一般情况下,将运算符重载为类的成员函数,是较好的选择☐重载为成员函数不能满足使用要求,重载为普通函数,又不能访问类的私有成员,所以需要将运算符重载为友元访问类的私有成员所以需要将运算符重载为class Complex {public:Complex(double r= 0.0, double i= 0.0):real(r), imaginary(i){}; //constructorComplex operator+(int r){return Complex(real + r, imaginary);}private:double real; // real partdouble real;//real partdouble imaginary; // imaginary part};7☐经过上述重载后:Complex c ;c = c + 5; //有定义,相当于c = c.operator +(5);但是:c = 5 + c; //编译出错☐为了使得上述表达式能成立,需要将+重载为普通函数Complex operator + ( int n, const Complex & c) {return Complex( c.real + n, c.imaginary);}8但是普通函数又不能访问私有成员,所以需要将运算符+重载为友元class Complex {public:Complex(double r= 0.0, double i= 0.0):real(r),imaginary(i){};real(r), imaginary(i){ }; //constructorComplex operator+(int r){p(,g y);return Complex(real + r, imaginary);}friend Complex operator+(int r, const Complex & C);private:double real; // real partdouble imaginary; // imaginary part};9Bug ReportVC60中如果使用了在VC 6.0中,如果使用了using namespace std;而且又将运算符重载为友元,编译时会出错,这个是VC6的bug,打上补丁后可以解决VS 2008无此问题10☐cout<< 5 << “this”;为什么能够成立?☐cout是什么?<<为什么能用在cout上?“”11☐cout是在iostream中定义的,ostream类的对象“”能用在“”☐<<能用在cout上是因为在iostream里对<<进行了重载☐考虑怎么重载才能使得cout<< 5;<<5;和cout<< “this”;都能成立?12☐有可能按以下方式重载:void operator<<(ostream& o, int n){Output(n);}☐假定Output( )是一个能将整数n输出到屏幕上的函数,至于其内部怎么实现,不必深究void operator<<(ostream& o, const char * s){Output(s);O()}13流插入运算符的重载cout<< 5 ; 即operator<<(cout, 5);cout<< this; 即operator<<(cout, this);<<“this”;operator<<(cout“this”);怎么重载才能使得cout 5 this ;<<5<<“this”;成立?14ostream&operator<<( ostream& o, int n){Output(n);return o;return o;}假定Output ( )是个能将整数n输出到屏幕上的函数,至于Output()是一个能将整数其内部怎么实现,不必深究ostream&operator<<( ostream& o, const char * s)p(,){Output(s);return o;} //用引用作为返回值是为了提高效率当然,也可能是ostream类将<< 重载为成员函数15cout << 5 << “this”;t<<5<<“thi”本质上的函数调用的形式是什么? operator<<(operator <<(cout, 5) , “this”);16假定下面程序输出为5hello, 请问该补写些什么?#include <iostream>using namespace std;class CStudent{l CSt d t{public:int nAge;int nAge;};int main(){CStudent s ;s.nAge= 5;s nAge=5;cout<< s <<"hello";t0return 0;}17ostream & operator<<( ostream & o,const CStudent & s){ o << s.nAge ;return o;return o;}18事实上在iostream里是将<<重载成成员函数class ostream{ostream& operator<<(int n) {Output(n);return * this;;}};那么,cout n n;<<n++<<n;的函数调用形式是什么呢?19cout operator<<(n++)cout.operator<<(n++).operator<<(n);实际上上面这条语句可以直接写在程序里其效果和 实际上,上面这条语句可以直接写在程序里,其效果和cout<< n++ << n;完全一样20int main()输入输出的例子{PhoneNumber phone; // create object phone cin >> phone;p cout << phone << endl;return 0;}输入:(213)765-0637(213) 7650637输出:(213) 765-063721#include <iostream>#include <iomanip>输入输出的例子#include <iomanip>//这个是为了后文的setw 函数using namespace std;22class PhoneNumber{private:char areaCode[4]; // 3-digit area codechar exchange[4]; // 3-digit exchangechar line[5]; // 4-digit lineh li[5]//4di i lifriend ostream&operator<<(ostream&output,const PhoneNumber&num);t Ph N b&) friend istream&operator>>(istream&, PhoneNumber&);// cin是istream类的//cin};ostream& operator<<( ostream&output, const PhoneNumber &operator<<(ostream&output,const PhoneNumber &num ){output << "(" << num.areaCode<< ")"<< num.exchange<< "-" << num.line;return output; // enables cout<< a << b << c;}23istream &operator>>( istream &input, PhoneNumber &num ) { input.ignore(); // skip “(”input >> setw(4) >> num.areaCode; // input area codeinput.ignore(); // skip “)” and spaceinput >> setw(4) >> num.exchange; // input exchangeinput>>setw(4)>>num exchange;//input exchangeinput.ignore(); // skip dash “-”input >> setw(5) >> num.line; // input linep();preturn input; // enables cin >> a >> b >> c;} // setw(n) 指定下一次只读取n个字符int main(){PhoneNumber phone; // create object phonePhoneNumber phone;//create object phonecin >> phone;cout << phone << endl;p;return 0;}24☐cin >> phone1>>int A;cin☐cout << "The phone number entered was: " << phone << endl;coutcout25class Arra {考虑编写一个整型数组类class Array{public:A (i t 10)i (){Array(int n = 10):size(n) { ptr = new int[n]; } ~Array() { d l t []t delete [] ptr;} i private:int size; // size of the array int *ptr; // pointer to first element of array };26该类的对象就代表一个数组,希望能像普通数组一样使用该类的对象。