您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > C++语言程序设计(清华大学郑莉)八
1第八章多态性清华大学郑莉C++语言程序设计C++语言程序设计清华大学郑莉2本章主要内容多态性运算符重载虚函数纯虚函数抽象类深度探索C++语言程序设计清华大学郑莉3多态性的概念多态性是面向对象程序设计的重要特征之一。多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为。多态的实现:–函数重载–运算符重载–虚函数C++语言程序设计清华大学郑莉4问题举例——复数的运算classComplex{//复数类声明public:Complex(doubler=0.0,doublei=0.0){real=r;imag=i;}voiddisplay()const;//显示复数的值private:doublereal;doubleimag;};运算符重载C++语言程序设计清华大学郑莉5问题举例——复数的运算用“+”、“-”能够实现复数的加减运算吗?实现复数加减运算的方法——重载“+”、“-”运算符运算符重载C++语言程序设计清华大学郑莉6运算符重载的实质运算符重载是对已有的运算符赋予多重含义必要性–C++中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类)实现机制–将指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参。–编译系统对重载运算符的选择,遵循函数重载的选择原则。运算符重载C++语言程序设计清华大学郑莉7运算符重载规则和限制可以重载C++中除下列运算符外的所有运算符:..*::?:只能重载C++语言中已有的运算符,不可臆造新的。不改变原运算符的优先级和结合性。不能改变操作数个数。经重载的运算符,其操作数中至少应该有一个是自定义类型。C++语言程序设计清华大学郑莉8两种形式重载为类的非静态成员函数重载为非成员函数运算符重载C++语言程序设计清华大学郑莉9运算符函数声明形式函数类型operator运算符(形参){......}重载为类成员函数时参数个数=原操作数个数-1(后置++、--除外)重载为非成员函数时参数个数=原操作数个数,且至少应该有一个自定义类型的形参。运算符重载C++语言程序设计清华大学郑莉10运算符成员函数的设计双目运算符B–如果要重载B为类成员函数,使之能够实现表达式oprd1Boprd2,其中oprd1为A类对象,则B应被重载为A类的成员函数,形参类型应该是oprd2所属的类型。–经重载后,表达式oprd1Boprd2相当于oprd1.operatorB(oprd2)运算符重载C++语言程序设计清华大学郑莉11运算符重载例8-1将“+”、“-”运算重载为复数类的成员函数。规则:–实部和虚部分别相加减。操作数:–两个操作数都是复数类的对象。#includeiostreamusingnamespacestd;classComplex{//复数类定义public://外部接口Complex(doubler=0.0,doublei=0.0):real(r),imag(i){}//构造函数Complexoperator+(constComplex&c2)const;//运算符+重载成员函数Complexoperator-(constComplex&c2)const;//运算符-重载成员函数voiddisplay()const;//输出复数private://私有数据成员doublereal;//复数实部doubleimag;//复数虚部};12ComplexComplex::operator+(constComplex&c2)const{//重载运算符函数实现returnComplex(real+c2.real,imag+c2.imag);//创建一个临时无名对象作为返回值}ComplexComplex::operator-(constComplex&c2)const{//重载运算符函数实现returnComplex(real-c2.real,imag-c2.imag);//创建一个临时无名对象作为返回值}13voidComplex::display()const{cout(real,imag)endl;}intmain(){//主函数Complexc1(5,4),c2(2,10),c3;//定义复数类的对象coutc1=;c1.display();coutc2=;c2.display();c3=c1-c2;//使用重载运算符完成复数减法coutc3=c1-c2=;c3.display();c3=c1+c2;//使用重载运算符完成复数加法coutc3=c1+c2=;c3.display();return0;}14程序输出的结果为:c1=(5,4)c2=(2,10)c3=c1-c2=(3,-6)c3=c1+c2=(7,14)15C++语言程序设计清华大学郑莉16运算符成员函数的设计前置单目运算符U–如果要重载U为类成员函数,使之能够实现表达式Uoprd,其中oprd为A类对象,则U应被重载为A类的成员函数,无形参。–经重载后,表达式Uoprd相当于oprd.operatorU()运算符重载C++语言程序设计清华大学郑莉17运算符成员函数的设计后置单目运算符++和--–如果要重载++或--为类成员函数,使之能够实现表达式oprd++或oprd--,其中oprd为A类对象,则++或--应被重载为A类的成员函数,且具有一个int类型形参。–经重载后,表达式oprd++相当于oprd.operator++(0)运算符重载C++语言程序设计清华大学郑莉18例8-2运算符前置++和后置++重载为时钟类的成员函数。前置单目运算符,重载函数没有形参,对于后置单目运算符,重载函数需要有一个整型形参。操作数是时钟类的对象。实现时间增加1秒钟。运算符重载#includeiostreamusingnamespacestd;classClock{//时钟类声明定义public://外部接口Clock(inthour=0,intminute=0,intsecond=0);voidshowTime()const;Clock&operator++();//前置单目运算符重载Clockoperator++(int);//后置单目运算符重载private://私有数据成员inthour,minute,second;};19//前置单目运算符重载函数Clock&Clock::operator++(){second++;if(second=60){second-=60;minute++;if(minute=60){minute-=60;hour=(hour+1)%24;}}return*this;}20//后置单目运算符重载ClockClock::operator++(int){//注意形参表中的整型参数Clockold=*this;++(*this);//调用前置“++”运算符returnold;}21//其它成员函数的实现略intmain(){ClockmyClock(23,59,59);coutFirsttimeoutput:;myClock.showTime();coutShowmyClock++:;(myClock++).showTime();coutShow++myClock:;(++myClock).showTime();return0;}22程序运行结果为:Firsttimeoutput:23:59:59ShowmyClock++:23:59:59Show++myClock:0:0:123C++语言程序设计清华大学郑莉24运算符非成员函数的设计函数的形参代表依自左至右次序排列的各操作数。后置单目运算符++和--的重载函数,形参列表中要增加一个int,但不必写形参名。如果在运算符的重载函数中需要操作某类对象的私有成员,可以将此函数声明为该类的友元。运算符重载C++语言程序设计清华大学郑莉25运算符非成员函数的设计双目运算符B重载后,表达式oprd1Boprd2等同于operatorB(oprd1,oprd2)前置单目运算符B重载后,表达式Boprd等同于operatorB(oprd)后置单目运算符++和--重载后,表达式oprdB等同于operatorB(oprd,0)运算符重载C++语言程序设计清华大学郑莉26例8-3将+、-(双目)重载为非成员函数,并将其声明为复数类的友元,两个操作数都是复数类的常引用。将(双目)重载为非成员函数,并将其声明为复数类的友元,它的左操作数是std::ostream引用,右操作数为复数类的常引用,返回std::ostream引用,用以支持下面形式的输出:coutab;该输出调用的是:operator(operator(cout,a),b);运算符重载#includeiostreamusingnamespacestd;classComplex{//复数类定义public://外部接口Complex(doubler=0.0,doublei=0.0):real(r),imag(i){}//构造函数friendComplexoperator+(constComplex&c1,constComplex&c2);//运算符+重载friendComplexoperator-(constComplex&c1,constComplex&c2);//运算符-重载friendostream&operator(ostream&out,constComplex&c);//运算符重载private://私有数据成员doublereal;//复数实部doubleimag;//复数虚部};27Complexoperator+(constComplex&c1,constComplex&c2){returnComplex(c1.real+c2.real,c1.imag+c2.imag);}Complexoperator-(constComplex&c1,constComplex&c2){returnComplex(c1.real-c2.real,c1.imag-c2.imag);}ostream&operator(ostream&out,constComplex&c){out(c.real,c.imag);returnout;}28C++语言程序设计清华大学郑莉29静态绑定与动态绑定绑定–程序自身彼此关联的过程,确定程序中的操作调用与执行该操作的代码间的关系。静态绑定–绑定过程出现在编译阶段,用对象名或者类名来限定要调用的函数。动态绑定–绑定过程工作在程序运行时执行,在程序运行时才确定将要调用的函数。C++语言程序设计清华大学郑莉34虚函数虚函数是动态绑定的基础。是非静态的成员函数。在类的声明中,在函数原型之前写virtual。virtual只用来说明类声明中的原型,不能用在函数实现时。具有继承性,基类中声明了虚函数,派生类中无论是否说明,同原型函数都自动为虚函数。本质:不是重载声明而是覆盖。调用方式:通过基类指针或引用,执行时会根据指针指向的对象的类,决定调用哪个函数。虚函数C++语言程序设计清华大学郑莉35例8-4#includeiostreamusingnamespacestd;classBase1{//基类Base1定义public:virtualvoiddisplay()const;//虚函数};voidBase1::display()const{coutBase1::display()endl;}classBase2:publicBase1{//公有派生类Base2定义public:voiddisplay()const;//覆盖基类的虚函数};voidBase2::display()const{coutBase2::display(
本文标题:C++语言程序设计(清华大学郑莉)八
链接地址:https://www.777doc.com/doc-5064013 .html