C++ 运算符重载 各类详细介绍
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
§7.2 运算符重载两种形式
运算符重载与函数重载相似,其目的是设置某一运算符,让 运算符重载与函数重载相似,其目的是设置某一运算符, 它具有另一种功能,尽管此运算符在原先C++ C++语言中代表另 它具有另一种功能,尽管此运算符在原先C++语言中代表另 一种含义,但他们彼此之间并不冲突。C++会根据运算符中 一种含义,但他们彼此之间并不冲突。C++会根据运算符中 的操作数来辨别应使用哪一种功能进行运算。 的操作数来辨别应使用哪一种功能进行运算。在类外定义运 算符重载函数,只能对类公有数据成员进行操作。实际上, 算符重载函数,只能对类公有数据成员进行操作。实际上, 运算符的重载有两种形式:定义为类的类友元函数; 运算符的重载有两种形式:定义为类的类友元函数;定义为 它将要操作的类的成员函数。前者称为友元运算符函数, 它将要操作的类的成员函数。前者称为友元运算符函数,后 者为成员运算符函数。 者为成员运算符函数。
运算符重载的定义格式: 运算符重载的定义格式:
• <函数类型> operator @[<运算符>](<形参表>) 函数类型> @[<运算符 ( 形参表> 运算符>] • { • <函数体>; 函数体> • } 在编译时遇到operator@的运算符函数, operator@的运算符函数 在编译时遇到operator@的运算符函数,就检查传递给函数 的参数的类型。 的参数的类型。如果编译器在一个运算符的两边有自定义的 数据类型。就执行用户自己的函数, 数据类型。就执行用户自己的函数,而不是内部运算符的常 规程序。 规程序。 那么上例中的错误,就是需要重载重载+运算符, 那么上例中的错误,就是需要重载重载+运算符,其运算符 函数operator+()如下: operator+()如下 函数operator+()如下:
双目运算符重载
• 当用友元函数重载双目运算符时,两个操作数都要传递 当用友元函数重载双目运算符时, 给运算符函数。 给运算符函数。 一般而言,采用友元函数重载双目运算符@后,也可以采用 一般而言,采用友元函数重载双目运算符@ 两种方法使用: 两种方法使用: • aa@bb //隐式调用 //隐式调用 • aa.operator@(bb)//显式调用 aa.operator@(bb)//显式调用 双目友元运算函数operator@所需的两个操作数都在参数表 双目友元运算函数operator@所需的两个操作数都在参数表 中由对象aa和bb显式提供 中由对象aa和bb显式提供 用友元运算符函数进行复数运算,见例7-2 用友元运算符函数进行复数运算,见例7
下面定义一个简化的复数类complex 下面定义一个简化的复数类complex • 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; //错误 //错误 • //… • return 0; • }
百度文库
友元运算符函数
• 概念 • 友元运算符函数定义的语法形式
声明
friend type operator@(形数表); operator@(形数表 形数表);
定义
type operator@(形数表) operator@(形数表 形数表) { //函数体} //函数体 函数体}
• 其中,type(<函数类型>)指定了重载运算符的返回值类型, 其中,type( 函数类型>)指定了重载运算符的返回值类型, >)指定了重载运算符的返回值类型 operator是定义运算符重载函数的关键词 是定义运算符重载函数的关键词, 运算符>) >)给 operator是定义运算符重载函数的关键词,@(<运算符>)给 定了要重载的运算符名称, C++中可重载的运算符 中可重载的运算符, 定了要重载的运算符名称,是C++中可重载的运算符,形参表 中给出重载运算符所需要的参数和类型 • 由于友元运算符函数不是类的成员函数,所以没有this指针。 由于友元运算符函数不是类的成员函数,所以没有this指针。 this指针 如果重载的运算符函数是双目的运算符, 如果重载的运算符函数是双目的运算符,则参数表中有两个 操作数,若为单目运算符, 操作数,若为单目运算符,则参数表中有一个操作数
第7章 运算符重载
本章主要内容
7.1 引入运算符重载的原因及运算符重载的规则 7.2 运算符重载函数的两种形式 7.3 几种常用运算符的重载 7.4 类型转换
本章重点
几种常用运算符的重载与类型转换
本章难点
单目运算符“++” 单目运算符“++”与“—”的重载
本章所需学时: 本章所需学时:
4学时
§7.1 运算符重载概述
int main() { complex A1(2,3,4.6).A2(3.6,2.8),A3,A4,A5,A6; A3=A1+A2; A4=A1A4=A1-A2; A5=A1*A2; A6=A1/A2; A1.print(); A2.print(); A3.print(); A4.print(); A5.print(); A6.print(); return 0; }
#include<iostream.h> class complex{ public: complex(double r=0.0,double i=0.0); void print (); friend complex operator+(complex a,complex b); friend complex operator-(complex a,complex b); operatorfriend complex operator*(complex a,complex b); friend complex operator/(complex a,complex b); private: double real; double imag; };
错误原因在于complex类类型不是预定义的基本数据类型, 错误原因在于complex类类型不是预定义的基本数据类型, complex类类型不是预定义的基本数据类型 而是用户自定义的数据类型。C++知道如何相加两个int数据 知道如何相加两个int数据, 而是用户自定义的数据类型。C++知道如何相加两个int数据, 或相加两个float型数据,甚至知道如何把一个int float型数据 int型数据与 或相加两个float型数据,甚至知道如何把一个int型数据与 一个float型数据相加,但是C++ float型数据相加 C++并不知道怎样将两个 一个float型数据相加,但是C++并不知道怎样将两个 complex类类型的对象进行相加,这样需要我们来重载“ complex类类型的对象进行相加,这样需要我们来重载“+” 类类型的对象进行相加 运算符来解决两对象相加的问题
complex:: complex(double r,double i); { real=r; imag=i;} complex operator+(complex a,complex b); { complex temp; temp.real=a.real+b.real; temp.imag=a.imag+b.imag; return temp;} complex operator-(complex a,complex b); operator{ complex temp; temp.real=a.real-b.real; temp.real=a.realtemp.imag=a.imagtemp.imag=a.imag-b.imag; return temp;} complex operator*(complex a,complex b); { complex temp; temp.real=a.real*b.real-imag*b.imag; temp.real=a.real*b.realtemp.imag=a.real*b.imag+imag*b.real; return temp;} complex operator/(complex a,complex b); { complex temp; double t; t=1/(b.real*b.real+b.imag*b.imag); temp.real=(a.real+b.real+a.imag*b.imag)*t; temp.imag=(b.real+a.realtemp.imag=(b.real+a.real-a.imag*b.imag)*t; return temp;} void complex::print() { cout<<real; if(imag>0) cout<<"+"; if(imag!=0) cout<<imag<<"i\ cout<<imag<<"i\n";}
运算符重载的规则
重载运算符与预定义运算符的使用方法完全相同,被重载的 重载运算符与预定义运算符的使用方法完全相同, 运算符不改变原来的操作数个数、优先级和结合性。 运算符不改变原来的操作数个数、优先级和结合性。 重载的运算符只能是运算符集中的运算符, 重载的运算符只能是运算符集中的运算符,不能另创新的运 算符。 算符。 运算符的含义可以改变,但最好不改变。 运算符的含义可以改变,但最好不改变。如实数的加法运算 可以用乘法运算符来实现 C++中 大多数系统预定义运算符可以把被重载, 在C++中,大多数系统预定义运算符可以把被重载,但也有 些运算符不能被重载如:类属关系运算符“ 些运算符不能被重载如:类属关系运算符“.”、成员指针 运算符“ 作用域分辨符“::” sizeof运算符和 运算符“*”、作用域分辨符“::”、sizeof运算符和 三目运算符“?:” 三目运算符“?:” 不能改变运算符对预定义类型的操作方式
说明
complex operator+(complex com1,complex com2) • { • complex temp; • temp.real=com1.real+com2.real; • temp.real=com1.imag+com2.imag; • return temp; • } • 在这个函数中,先用类的构造函数来生成一个临时对象 在这个函数中, temp,执行return 语句时会调用拷贝构造函数, temp,执行return 语句时会调用拷贝构造函数,把temp 的值拷贝到主调函数中的一个无名对象中。 的值拷贝到主调函数中的一个无名对象中。当函数 operator+()结束时 会调用析构函数析构对象temp 结束时, temp。 operator+()结束时,会调用析构函数析构对象temp。这 个过程程序开销较大,于是可以将上述程序改为:直接 个过程程序开销较大,于是可以将上述程序改为: 用类的构造函数来生成一个临时对象, 用类的构造函数来生成一个临时对象,而不对该对象进 行命名。则上述程序段可以改为: 行命名。则上述程序段可以改为:
complex operator+(complex com1,complex com2)
• { • complex temp; • temp.real=com1.real+com2.real; • temp.real=com1.imag+com2.imag; • return temp; • } 其中主函数的 • total=com1+com2;(隐式调用) ;(隐式调用 total=com1+com2;(隐式调用) 语句也可以写成: 语句也可以写成: • 显式调用) total=operator+(com1,com2); (显式调用) 从中可以看出运算符重载进一步提高了面向对象软件系统的 灵活性、 灵活性、可扩充性和可读性
引入运算符重载的原因
• 例如:int a=1,b=2;float c=1.1,d=2.4; 例如: • int e=a+b; float f=c+d; float g=f+e; • 为什么同一个运算符“+”可以用于完成不同类型的数 为什么同一个运算符“ 据的加运算呢?原来C++语言针对预定义数据类型已经对 据的加运算呢?原来C++语言针对预定义数据类型已经对 某些运算符做了适当的重载。 某些运算符做了适当的重载。 • C++语言提供的预定义数据类型终究是有限的,我们在解 C++语言提供的预定义数据类型终究是有限的 语言提供的预定义数据类型终究是有限的, 决多种多样的实际问题 时,往往需要使用许多的自定义 数据类型。例如,在解决科学与工程计算问题时, 数据类型。例如,在解决科学与工程计算问题时,往往 要使用复数、矩阵等。 要使用复数、矩阵等。