第十三章 运算符重载

合集下载

13.1 运算符重载

13.1 运算符重载

说明:程序中出现的表达式 c1+c2 编译程序将其解释为: c1.operator+(c2); 其中,c1和c2是complex类的对象,而operator+( )是运算符 “+”的重载函数。 同理 c1-c2 解释为: c1.operator-(c2); 因此:A行 c4+=c1+c2; 被解释为: c4.operaotr+=(c1.operaotr+(c2));
说明: ★程序中的A行调用构造函数产生一个临时对象,并返回该 临时对象的值。 我们已经知道,对于双目运算符,重载为类的成员函数时, 仅有一个参数;重载为友元函数时,有两个参数,因此,当 程序中出现: c1+c2 编译系统将其解释为 operator+(c1, c2); 这将调用如下的函数进行求值运算: complex operator+(complex &c1, complex &c2);
(4)运算符的重载实际上是函数的重载。不同之处在于系 统约定了重载运算符的函数名,operator @( ); (5)不可臆造新的运算符。必须把重载运算符限制在C++ 语言中已有的运算符范围内的允许重载的运算符之中。
2. 重载为友元函数
运算符重载函数还可以为友元函数。当重载为友元函数 时,由于友元函数不是类的成员函数,尽管它可以访问类的 所有成员(包括私有成员),但必须通过类的对象才能实现 这种访问,因此当运算符重载为友元函数时,对于双目运算, 友元函数必须有2个参数,对于单目运算符,友元函数也必须 有一个参数。 注意,有些运算符不能重载为友元函数,它们是: =,(),[ ]和->。
Complex operator +(Complex &c1, Complex &c2) { Complex t; t.Real=c1.Real+c2.Real; t.Image=c1.Image+c2.Image; return t; } Complex operator+(Complex c1, float s) { Complex t; t.Real=c1.Real+s; t.Image=c1.Image; return t; }

C++基础系列——运算符重载

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运算符重载其实就是定义⼀个函数,在函数体内实现想要的功能,当⽤到该运算符时,编译器会⾃动调⽤这个函数,它本质上是函数重载。

第12-13讲 运算符重载

第12-13讲 运算符重载
7
7.1.2 运算符重载规则
可以重载C++中除下列运算符外的所有运算符: 类属关系运算符. 成员指针运算符* 作用域分辨符:: sizeof运算符 三目运算符?: 只能重载C++语言中已有的运算符,不可臆造新的。 不能改变操作数个数。 不能改变原运算符的优先级和结合性。 不能改变运算符对预定义类型数据的操作方式。 经重载的运算符,其操作数中至少应该有一个是自定 义类型。
14

void complex:: print()//显示输出复数 { cout<<real; if(imag>0) cout<<"+"; if(imag!=0) cout<<imag<<"i";cout<<endl; } void main() { complex A1(2.3,4.6),A2(3.6,2.8),A3,A4,A5,A6;//定义6个复数类对象 A1.print(); A2.print(); A3=A1+A2; A3.print(); A4=A1-A2; A4.print(); A5=A1*A2; A5.print(); A6=A1/A2; A6.print(); }
2

class complex { public: double real,imag; //定义一个实部,一个虚部变量 complex(double r=0,double i=0) { real=r; imag=I; } }; main() { complex com1(1.1,2.2),com2(3.3,4.4),total; total=com1+com2; 错误,2个自定义的数据类 return 0; 型complex类型对象相加, } C++无法实现. 希望实现total=com1+com2;重载“+”

C++电子教案第十三章 运算符重载

C++电子教案第十三章 运算符重载
北京源智天下科技有限公司
1-7
• • • • • •
联系方式:
运算符重载为类的友元函数
• 将重载的运算符函数定义为类的友元函数,称为友元运算符 函数。友元运算符函数不是类的成员,其在类内声明原型, 在类外定义函数本身。由于友元运算符函数不是类的成员函 数,不属于任何一个类对象,所以没有this指针,因此,重 载双目运算符时要有两个参数,重载单目运算符时只要一个 参数就可以了。一般来说,友元运算符函数在类内声明的一 般形式为: friend<返回类型> operator<运算符>(参数表); 在类外定义的一般形式为: <返回类型> operator<运算符>(参数表) { 函数体 }
运算符重载简介

简单来说,运算符重载是实现编译时的多态性的另外一 种形式。运算符重载是对已有的运算符赋予多重含义, 使同一个运算符作用于不同类型的数据时,导致不同类 型的行为。
运算符重载的实质是函数重载。事实上,C++语言中的 每一个运算符对应着一个运算符函数,在实现过程中, 把指定的运算表达式中的运算符转化为对运算符函数的 调用,而表达式中的运算对象转化为运算符函数的实参, 这个过程是在编译阶段完成的。
C++中为什么要支持运算符重载,其好处如何体现? 运算符重载的规则有哪些? 运算符重载有两种形式,其分别是什么? 写一个程序测试输入的长度能否构成一个三角形。构成 三角形的条件是任意两边之和大于第三边。
北京源智天下科技有限公司
1-12
联系方式:

北京源智天下科技有限公司
1-3
联系方式:
运算符重载的特点

尽管运算符重载是一种特殊的函数重载,但相比函数重 载,运算符重载有着自身的一些特点。使用operator关 键字对重载函数进行标识和定义。运算符有 3种形式, 即中缀、后缀、前缀,它们的 operator 表示形式如表 13-1所示。

运算符重载

运算符重载

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 程序设计 教学课件 ppt 第13章_运算符重载

C  程序设计 教学课件 ppt 第13章_运算符重载
C++程序设计,郑莉,清华大学 13
13.2 运算符重载为成员函数
Complex Complex::operator - () { return Complex(-real, -image);
} Complex Complex::operator + (const Complex &c) {
return Complex(real + c.real, image + c.image); } int main() {
• 运算符重载为类的成员函数时,函数的参数个数 比运算符原来的操作数少一个(后置++、--除外) ,这是因为重载为类的成员函数的话,该类的对象 使用此运算符时,相当于在操作数中隐式包含了指 向对象本身的this指针,自身的数据可以直接访问 ,这样就不需要再在参数表中写一个“this”进行 传递了
▫ 重载一元运算符时,操作数由指向对象的this指针提 供,因此不需要在参数表中提供任何参数;重载二元 运算符时,参数表中的唯一参数默认为右操作数,而 将this视为左操作数
)以及流输入输出操作符(<<, >>)都可以重载
C++程序设计,郑莉,清华大学 5
13.1 运算符重载的规则
• 重载运算符必须至少有一个类类型的操作数。而 用于内置类型的运算符的定义不可以改变。不能 为任何内置类型定义新的运算符,例如不能定义 两个数组的加法运算符
▫ 例如不可以重载用于整型的加号运算符: int operator + (int, int); //以上操作违法,不可 以重载用于内置类型的运算符
C++程序设计,郑莉,清华大学 19
13.3 运算符重载为非成员函数

运算符重载

运算符重载
CCS E
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. 逻辑运算符重载逻辑运算符包括条件运算符和逻辑非运算符。

每个逻辑运算符都有一组默认的行为,可以通过运算符重载来自定义它们的行为。

运算符重载

运算符重载

运算符重载为类的友元函数
类中的声明: 类中的声明: friend 函数类型 operator 运算符(参数表); 运算符(参数表); 运算符重载函数的定义形式: 运算符重载函数的定义形式: 运算符(参数表) 函数类型 operator 运算符(参数表) { 函数体; 函数体; } 附加例) (附加例)用友元函数实现复数的加法运算符的重 载。
数据类型转换 标准数据类型转换
隐式转换: 自动转成double型) 隐式转换:7.5+2 (将2自动转成 将 自动转成 型 显式转换: 转成整型) 显式转换:int(89.5) (将89.5转成整型 将 转成型
涉及到类类型的转换
对于用户自己声明的类型, 对于用户自己声明的类型,编译系统并不知道怎样进行转 换。解决这个问题的关键是让编译系统知道怎样去进行转 换,需要定义专门的处理函数。 需要定义专门的处理函数。 将一个其他类型的数据转换成一个类类型: 将一个其他类型的数据转换成一个类类型:转换构造函数 将一个类的对象转换成另一类型的数据: 将一个类的对象转换成另一类型的数据:类型转换函数
运算符重载的格式
运算符重载为类的成员函数 运算符重载为类的友元函数
运算符重载的规则

② ③ ④ ⑤
.”、 *” ::”、 ?:”和 sizeof”等几个运 除“. 、“*”、“:: 、“?: 和“sizeof 等几个运 算符不能重载外, 算符不能重载外,C++中几乎所有的运算符都可以 中几乎所有的运算符都可以 重载。 重载。 运算符被重载后,其优先级和结合性不会改变。 运算符被重载后,其优先级和结合性不会改变。 不能改变运算符操作对象的个数。 不能改变运算符操作对象的个数。 运算符的意义应不变。 运算符的意义应不变。 用于类对象的运算符一般必须重载,但有两个例外, 用于类对象的运算符一般必须重载,但有两个例外, 运算符“ 和 不必用户重载。 运算符“=”和“&”不必用户重载。 不必用户重载

运算符重载——精选推荐

运算符重载——精选推荐

运算符重载运算符重载学习运算符重载,让运算符能做⼀些原来做不了的事情,⽅便它的使⽤⼀、运算符重载的概念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)不能返回局部变量的引⽤。

13 函数与运算符重载

13 函数与运算符重载

使用“类名::”加以区分。 根据调用函数对象加以区分。
函数重载
范例 #include <iostream.h> class point { int x,y; public: point(int x,int y) { point::x=x; point::y=y; } float area() {return 0.0;} }; class circle:public point { int r; public: circle(int x,int y,int r1):point(x,y) { r=r1;} float area(){ return 3.14*r*r;} };
多态性概念

因此:

封装性是基础,用于实现类的定义; 继承性是关键,实现代码与数据的重用; 而多态性是补充,实现不同的行为表现,解决 程序的复杂性和易用性。 函数重载 运算符重载 动态联编

多态性的表现形式:

函数重载

C++中,当有一组函数完成相似功能时,函数名 允许重复使用,编译器根据参数表中参数的个数 或类型(不能根据形参变量名)来判断调用哪一 个函数,这就是函数的重载,且可以是成员函数 也可以是非成员函数。 重载函数仅仅靠函数的参数表,即参数的个数或 参数的类型进行区别。仅仅返回值不同的重载函 数是非法的。
高级语言(C++)程序设计
第15讲 函数与运算符重载
主要内容(2学时)

多态性概念 函数重载 运算符重载
多态性概念

面向对象中的多态性指系统发出同样的消 息被不同类型的对象接受时导致不同的行 为。这里的消息可理解为成员函数的调用, 而不同行为是指不同的函数实现。

C++运算符重载(简单易懂)

C++运算符重载(简单易懂)

C++运算符重载(简单易懂)运算符重载,就是对已有的运算符重新进⾏定义,赋予其另⼀种功能,以适应不同的数据类型。

你可以重定义或重载⼤部分 C++ 内置的运算符。

例如 + 、 - 、 * 、 / 、++、--、>>、<<等,这样,你就能使⽤⾃定义类型的运算符。

运算符重载的基本格式重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。

与其他函数⼀样,重载运算符有⼀个返回类型和⼀个参数列表。

Point operator+(const Point &);运算符重载有两种⽅式:⼀种是类内重载(运算符重载函数作为类的成员函数),另⼀种是类外重载(运算符重载函数作为类的友元函数)类内重载#include <iostream>using namespace std;class Point{public:Point(){};Point (int x, int y): x(x),y(y) {};Point operator+(const Point &a){ //类内重载,运算符重载函数作为类的成员函数Point ret;ret.x = this->x + a.x;ret.y = this->y + a.y;return ret;}int x,y;};int main() {Point a(2,4),b(5,3);Point c = a + b;cout<< "x :" << c.x << endl;cout<<"y :" << c.y << endl;}当上⾯的代码被编译和执⾏时,它会产⽣下列结果:x : 7y: 7运算符重载是类内重载时,运算符重载函数作为类的成员函数,以上述代码为例 a + b 相当于 a 对象调⽤+⽅法并且传⼊参数时 b 对象类外重载#include <iostream>using namespace std;class Point{public:Point(){};Point (int x, int y): x(x),y(y) {};friend Point operator+(const Point &, const Point &);int x,y;};Point operator+(const Point &a,const Point &b){//类外重载,运算符重载函数作为类的友元函数Point ret;ret.x = a.x + b.x;ret.y = a.y + b.y;return ret;}int main() {Point a(2,4),b(5,3);cout<< "x :" << c.x << endl;cout<<"y :" << c.y << endl;}当上⾯的代码被编译和执⾏时,它会产⽣和上⾯⼀样的结果各种运算符重载实例下⾯将进⾏各种运算符重载实例的代码演⽰,演⽰⼏种基本的运算符重载。

运算符重载——精选推荐

运算符重载——精选推荐

运算符重载什么是运算符的重载?运算符与类结合,产⽣新的含义。

为什么要引⼊运算符重载?作⽤:为了实现类的多态性(多态是指⼀个函数名有多种含义)怎么实现运算符的重载?⽅式:类的成员函数或友元函数(类外的普通函数)规则:不能重载的运算符有 . 和 .* 和 ?: 和 :: 和 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可以是任意整数。

C++学习之运算符重载的总结

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)运算符重载可以通过成员函数的形式,也可是通过友元函数,⾮成员⾮友元的普通函数。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

CArray::CArray(int n) { if(n>0){ arp=new int[n]; memset(arp,0,sizeof(int)*n); //string.h len=n; } else{ len=0;arp=0;} }
int & CArray::operator[](int index) {
数组下标运算符[ 5. 数组下标运算符[ ] 重载下标运算符的一般格式为: <类型> operator[ ](<参数>) {…} //函数体 其中<参数>为一个参数,且仅有一个 参数,该参数设定了下标值,通常为整 型。 下标运算符必须利用类的成员函数来实 现,而不能使用友元函数。
class ainteger { 【例1】下标是否越界的检验 下标是否越界的检验 int *a; int sz; public: ainteger ai(10); ainteger( int size) ai[2]=3; { sz=size; int i=ai[2]; a=new int[size]; } int & operator[ ](int i ) { if(i<0 || i>=sz) ai.operator[](2) { cout<<“error”<<endl; 返回ai::a[2]的引用 exit(1); } return a[i]; } ~ainteger ( ) { delete [ ]a; } };
【例】利用类的缺省赋值运算符产生的指针悬挂问题 class CA { char *ps; public: CA(){ps=0;} CA(char *s) { ps=new char[strlen(s)+1]; strcpy(ps,s); } ~CA(){if(ps) delete[]ps;} char *GetS(){return ps;} };
程序编译没有问题,但运行时出错!
缺省赋值语句产生指针悬挂问题示意图。
s1 s2 s1=s2 “China!” “Computer!” “China!” “Computer!” s1 s2
无法撤消 s1 撤消s2 “China!” “Computer!” 已不存在 指针悬挂 撤消s1 出错
此时在类CA中可以对赋值运算符进行如下重载。
【例2】对下标运算符进行重载,使之具有检查下 对下标运算符进行重载, 对下标运算符进行重载 标是否越界的功能 class Carray { int len; int *arp; public: CArray(int n=0); ~CArray() {if (arp) delete[]arp;} int & operator[] (int index); // 定义重载的下标运算符 };
void main(void) { CA s1("China!"),s2("Computer!"); cout<<"s1="<<s1.GetS()<<'\t'; cout<<"s2="<<s2.GetS()<<'\n'; s1=s2; //A产生指针悬挂 //A产生指针悬挂
cout<<"s1="<<s1.GetS()<<'\t'; cout<<"s2="<<s2.GetS()<<'\n'; }
乘号* 利用成员函数重载) 利用成员函数重载 2. 乘号* (利用成员函数重载 C C:: operator*(C m ) { C temp; temp.x=x*m.x; return temp; } C a,b; C c=a*b; a.operator*(b)
乘号* 利用友元函数重载) 利用友元函数重载 2. 乘号*(利用友元函数重载 先在类中声明: friend C operator*(C ,C); 再在类外定义: C operator*(C m1, C m2 ) { C temp; temp.x=m1.x*m2.x; return temp; } C a,b; C c=a*b; Operator*(a,b)
后置运算符-- 利用友元函数重载) 利用友元函数重载 3. 后置运算符-- (利用友元函数重载 class C{ private: double x; C A(1); public: A--; C( ) { x=0.0; } C(double a) { x=a; } friend C operator--(C &,int); }; 整型参数没有 C operator--(C &t,int) 特别的意义,只是 特别的意义, { t.x--; 标识重载的是后置 运算符。 运算符。 return t; }
二.双目运算符重载
加号+ 利用成员函数重载) 利用成员函数重载 1. 加号+ (利用成员函数重载 C C:: operator+(C m ) { C temp; temp.x=x+m.x; return temp; } C a,b; C c=a+b; a.operator+(b)
加号+ 利用友元函数重载) 利用友元函数重载 1. 加号+ (利用友元函数重载 先在类中声明: friend C operator+(C ,C); 再在类外定义: C operator+(C m1, C m2 ) { C temp; temp.x=m1.x+m2.x; return temp; } C a,b; C c=a+b; operator+(a,b)
一.单目运算符重载
负号“ 利用成员函数重载 1. 负号“-” (利用成员函数重载 利用成员函数重载) C C:: operator - ( ) { C temp; temp.x=-x; return temp; } C c=-a; a.operator-( )
负号“-” (利用友元函数重载 利用友元函数重载 1. 负号 利用友元函数重载) class C{ //… public: friend C operator-(const C); //… }; C operator- (const C m ) { C temp; temp.x=-m.x; return temp; } C c=-a; operator-(a)
利用成员函数重载 3. 后置运算符-- (利用成员函数重载 利用成员函数重载) class C{ private: double x; C A(1); public: A--; C( ) { x=0.0; } C(double a) { x=a; } 整型参数没有 C operator--(int) 特别的意义,只是 特别的意义, { x--; 标识重载的是后置 return *this; 运算符。 运算符。 } };
void main(void) { CArray m1(10),m2(3); int i; // for(i=0;i<10;i++) m1[i]=i; / 重载数组下标的使用 for(i=1;i<11;i++) cout<<m1[i]<<" cout<<'\n'; m2[2]=26; cout<<"m2[2]="<<m2[2]<<'\n'; } "; //B //C
CA & CA::operator=(CA &b) { if(ps) dele [strlen(b.ps)+1]; strcpy(ps,b.ps); } else ps=0; return *this; }
对赋值运算符进行重载时要注意以下三点: 一是只能利用成员函数重载,不能用 友元函数重载; 二是重载的赋值运算符不能被继承; 三是不能将赋值运算符重载函数声明 为虚函数。
C a(10), b(3); 希望c=a+b; 希望 加法运算符重载函数(利用成员函数重载) 利用成员函数重载 利用成员函数重载 class C{ //…… public: C operator+(C m) //定义方式 { C temp(x+m.x); return temp; } //…… }; C a(10), b(3), c; a.operator+(b) c=a+b; 赋值运算符一般用预定义的 C c=a.add(b);
单目运算符重载中成员函数重载与友元函 数重载之间的区别: 用成员函数重载单目运算符,由于此时 运算符的操作数为当前对象,因此用成员 函数重载单目运算符时无参数。 由于友元函数非成员函数,不能使用 this指针,因此用友元函数重载单目运算 符时必须带有一个参数作为该运算符的操 作数。
前置运算符++ 利用成员函数重载) 利用成员函数重载 2. 前置运算符++ (利用成员函数重载 class C{ private: double x; C A(1); public: C( ) { x=0.0; } ++A; C(double a) { x=a; } C operator++() { x++; return *this; } };
第十三章 运算符重载
运算符——一种函数;对于类对象,用户可重新定义运算符函数。
引 子
class C{ private: double x; public: C( ) { x=0.0; } C(double a) { x=a; } C add(const C m) { C temp; temp.x=m.x+x; return temp; } };
相关文档
最新文档