第4章运算符重载2
- 格式:ppt
- 大小:546.50 KB
- 文档页数:27
实验9 运算符重载(1)一、实验目的1、掌握运算符重载的概念;二、实验内容1、用成员函数重载运算符,使对整型的运算符=、+、-、*、/ 适用于分数运算。
要求:(1)输出结果是最简分数(可以是带分数);(2)分母为1,只输出分子。
过程分析:1) 定义一个类Complex,在公共部分定义构造函数,输出函数,和运算符=、+、-、*、/的重载函数,此处运算符=可以使用系统默认的运算符=的函数。
在私有部分定义两个数据成员x和y。
2) 定义构造函数时先在类里面声明构造函数,并对参数初始化,再在类外定义构造函数,分别给x和y初始化。
3) 定义输出函数print(),对分数进行化简,采用的方法是利用for循环,分子分母均除以i,i从2增加到分子分母中更小的一个数后截止,每次增加1,在利用if else 语句,如果分子分母除以i均被整除,则说明这是的i是分子分母的公约数,分子分母均赋值为整除后的结果值,同时将i重新赋值为2,因为再求公约数是要再从i=2开始循环;否则i++,表示及进入下一个循环。
化成最简形式后在利用if else语句,判断最终结果值的分母是否为1,如果不是,则输出分数,否则只输出分子。
4) 定义运算符+重载函数,参数作为+的右操作对象,调用函数的对象作为左操作对象,在函数里定义一个Complex对象d,将左右操作对象的分数相加,将得到的结果的分子和分母分别赋给d的分子和分母,返回类的对象d。
5) 定义运算符-重载函数,参数作为-的右操作对象,调用函数的对象作为左操作对象,在函数里定义一个Complex对象d,将左右操作对象的分数相减,并将得到的结果的分子和分母分别赋给d的分子和分母,返回类的对象d。
6) 定义运算符*重载函数,参数作为*的右操作对象,调用函数的对象作为左操作对象,在函数里定义一个Complex对象d,将左右操作对象的分数相乘,并将得到的结果的分子和分母分别赋给d的分子和分母,返回类的对象d。
简述运算符重载的规则
运算符重载可以用来定义自定义类型的操作行为。
以下是运算符重载的规则:
1. 运算符重载函数必须是类或枚举类型的成员函数或全局函数。
2. 运算符重载函数的名称必须是“operator”加上要重载的运算符符号,例如“operator +”或“operator <<”。
3. 运算符重载函数必须指定参数列表,包括参数类型和数量,不能有默认值。
4. 运算符重载函数可以返回任何类型,但不能返回void 类型。
5. 运算符重载函数可以是const 成员函数,如果不会修改对象的状态。
6. 运算符重载函数可以被重载多次,只要参数列表不同。
7. 运算符重载函数不能改变运算符的优先级和结合性,也不能改变运算符的语法。
8. 运算符重载应该符合语义上的期望,例如“+”操作符应该执行加法,而不是减法。
9. 运算符重载应该遵循刚才提到的运算符的语法和行为。
总之,运算符重载在正确地使用时,可以使代码更加直观,易于理解,也可以让自定义数据类型具有更多的功能和操作。
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;}。
简述运算符重载的规则。
篇一:运算符重载是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. 逻辑运算符重载逻辑运算符包括条件运算符和逻辑非运算符。
每个逻辑运算符都有一组默认的行为,可以通过运算符重载来自定义它们的行为。
运算符重载运算符重载学习运算符重载,让运算符能做⼀些原来做不了的事情,⽅便它的使⽤⼀、运算符重载的概念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++学习之路—运算符重载(⼆)运算符重载作为类的成员函数和友元函数对运算符重载的函数有两种处理⽅式:(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++为运算符重载提供了⼀种⽅法,即运算符重载函数。
其函数名字规定为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}对于单⽬运算符⽽⾔,当前对象作为运算符的操作数。
运算符重载详解1.运算符重载定义:C++中预定义的运算符的操作对象只能是基本数据类型。
但实际上,对于许多⽤户⾃定义类型(例如类),也需要类似的运算操作。
这时就必须在C++中重新定义这些运算符,赋予已有运算符新的功能,使它能够⽤于特定类型执⾏特定的操作。
运算符重载的实质是函数重载,它提供了C++的可扩展性,也是C++最吸引⼈的特性之⼀。
运算符重载是通过创建运算符函数实现的,运算符函数定义了重载的运算符将要进⾏的操作。
运算符函数的定义与其他函数的定义类似,惟⼀的区别是运算符函数的函数名是由关键字operator和其后要重载的运算符符号构成的。
运算符函数定义的⼀般格式如下:<返回类型说明符> operator <运算符符号>(<参数表>){<函数体>} 2.运算符重载时要遵循以下规则:(1) 除了类属关系运算符"."、成员指针运算符".*"、作⽤域运算符"::"、sizeof运算符和三⽬运算符"?:"以外,C++中的所有运算符都可以重载。
(2) 重载运算符限制在C++语⾔中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符。
(3) 运算符重载实质上是函数重载,因此编译程序对运算符重载的选择,遵循函数重载的选择原则。
(4) 重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构。
(5) 运算符重载不能改变该运算符⽤于内部类型对象的含义。
它只能和⽤户⾃定义类型的对象⼀起使⽤,或者⽤于⽤户⾃定义类型的对象和内部类型的对象混合使⽤时。
(6) 运算符重载是针对新类型数据的实际需要对原有运算符进⾏的适当的改造,重载的功能应当与原有功能相类似,避免没有⽬的地使⽤重载运算符。
(7)重载运算符的函数不能有默认的参数,否则就改变了运算符的参数个数,与前⾯第3点相⽭盾了;(8)重载的运算符只能是⽤户⾃定义类型,否则就不是重载⽽是改变了现有的C++标准数据类型的运算符的规则了,会引会天下⼤乱的;(9)⽤户⾃定义类的运算符⼀般都必须重载后⽅可使⽤,但两个例外,运算符“=”和“&”不必⽤户重载;(10)运算符重载可以通过成员函数的形式,也可是通过友元函数,⾮成员⾮友元的普通函数。