第6章 多态性和虚函数_第1页
第6章 多态性和虚函数_第2页
第6章 多态性和虚函数_第3页
第6章 多态性和虚函数_第4页
第6章 多态性和虚函数_第5页
已阅读5页,还剩43页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第第6 6章章 多态性和虚函数多态性和虚函数 l多态性是面向对象程序设计的重要特征之一。多态性是面向对象程序设计的重要特征之一。l多态性是指多态性是指发出同样的消息被不同类型的对象发出同样的消息被不同类型的对象接收时导致完全不同的行为接收时导致完全不同的行为。l消息消息主要指主要指对类的成员函数的调用对类的成员函数的调用。l多态的实现:多态的实现: 函数重载函数重载 运算符重载运算符重载 虚函数动态:运行时的多态虚函数动态:运行时的多态静态:编译时的多态静态:编译时的多态2021-7-272不同人对不同人对play()请求的响应请求的响应联编(联编(binding):是指计算机程序自身彼此关联

2、的过程是指计算机程序自身彼此关联的过程联编工作在编译连接阶段完成的情况称为:联编工作在编译连接阶段完成的情况称为:静态联编静态联编联编在程序运行阶段完成的情况称为:联编在程序运行阶段完成的情况称为:动态联编动态联编。第第6 6章章 多态性和虚函数多态性和虚函数 6.1 6.1 运算符重载运算符重载6.2 6.2 虚函数虚函数6.3 6.3 纯虚函数和抽象类纯虚函数和抽象类6.4 6.4 虚析构函数虚析构函数习题习题6.1 6.1 运算符重载运算符重载1.运算符重载的实质运算符重载的实质l运算符重载是对运算符重载是对已有已有的运算符赋予多重含义的运算符赋予多重含义l必要性必要性 C+中预定义的运

3、算符其运算对象只能是基中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型本数据类型,而不适用于用户自定义类型(如类)(如类)l实现机制实现机制 将指定的运算表达式转化为将指定的运算表达式转化为对运算符函数的对运算符函数的调用调用,运算对象运算对象转化为运算符函数的转化为运算符函数的实参实参。 编译系统对重载运算符的选择,遵循函数重编译系统对重载运算符的选择,遵循函数重载的选择原则。载的选择原则。不能重载的运算符不能重载的运算符是:是:(1) (1) 成员访问运算符成员访问运算符. .(2) (2) 作用域运算符作用域运算符(3) (3) 条件运算符条件运算符?:?:(4)

4、(4) 成员指针运算符成员指针运算符* *(5) (5) 编译预处理命令的开始符号编译预处理命令的开始符号# #l只能重载只能重载C+语言中已有的运算符,不可臆造语言中已有的运算符,不可臆造新的。新的。l不改变原运算符的优先级和结合性。不改变原运算符的优先级和结合性。l不能改变操作数个数。不能改变操作数个数。l经重载的运算符,其操作数中至少应该有一个经重载的运算符,其操作数中至少应该有一个是自定义类型。是自定义类型。l重载为类成员函数。重载为类成员函数。l重载为友元函数。重载为友元函数。可以参考以下的经验:可以参考以下的经验: (1)(1)只能使用只能使用成员函数成员函数重载的运算符有:重载的

5、运算符有:= =、()()、-、newnew、deletedelete。 (2)(2)单目运算符最好重载为单目运算符最好重载为成员函数成员函数。 (3)(3) 对于复合的赋值运算符如对于复合的赋值运算符如+=+=、-=-=、* *= =、/=/=、&=&=、!=!=、=、%=%=、=、=建议重载为建议重载为成员函数成员函数。 (4)(4) 对于其它运算符,建议重载为对于其它运算符,建议重载为友元函数友元函数。 除了除了赋值运算符赋值运算符外,其它运算符函数都可以由外,其它运算符函数都可以由派生类派生类继承继承,并且派生类还可有选择地重载自己所需要的运算,并且派生类还可有选择地重载自己所需要的运

6、算符(包括基类重载的运算符)。符(包括基类重载的运算符)。 运算符重载的实质就是函数重载。运算符重载的实质就是函数重载。 type operator ( type operator (参数表参数表) )若运算符是一元的,则参数表为空,此时当前对象作为此运若运算符是一元的,则参数表为空,此时当前对象作为此运算符的单操作数;若运算符是二元的,则参数表中有一个操作算符的单操作数;若运算符是二元的,则参数表中有一个操作数,此时当前对象作为此运算符的左操作数,参数表中的操作数,此时当前对象作为此运算符的左操作数,参数表中的操作数作为此运算符的右操作数,依此类推。数作为此运算符的右操作数,依此类推。 运算

7、符函数的定义方式同一般成员函数,对类成员的访问与运算符函数的定义方式同一般成员函数,对类成员的访问与一般成员函数相同,定义如下:一般成员函数相同,定义如下:type type 类名类名:operator operator (参数表)参数表) / / 运算符处理程序代码运算符处理程序代码 重载运算符的使用方法同原运算符一样,只是它的操作数一重载运算符的使用方法同原运算符一样,只是它的操作数一定要是定义它的特定类的对象。定要是定义它的特定类的对象。l声明形式声明形式函数类型函数类型 operator 运算符(形参)运算符(形参) .l重载为类成员函数时重载为类成员函数时 参数个数参数个数=原操作数

8、个数原操作数个数-1 (后置(后置+、-除外)除外)l重载为友元函数时重载为友元函数时 参数个数参数个数=原操作数个数原操作数个数,且至,且至少应该有一个自定义类型的形参。少应该有一个自定义类型的形参。例题例题【例【例6.16.1】用成员函数重载运算符一用成员函数重载运算符一 【例【例6.26.2】用成员函数重载运算符二用成员函数重载运算符二 l双目运算符双目运算符 B 如果要重载如果要重载 B 为类成员函数,使之能够实现表为类成员函数,使之能够实现表达式达式 oprd1 B oprd2,其中,其中 oprd1 为为A 类对象,类对象,则则 B 应被重载为应被重载为 A 类的成员函数,形参类型

9、类的成员函数,形参类型应该是应该是 oprd2 所属的类型。所属的类型。 经重载后,表达式经重载后,表达式 oprd1 B oprd2 相当于相当于 oprd1.operator B(oprd2)l前置单目运算符前置单目运算符 U 如果要重载如果要重载 U 为类成员函数,使之能够实现为类成员函数,使之能够实现表达式表达式 U oprd,其中,其中 oprd 为为A类对象,则类对象,则 U 应被重载为应被重载为 A 类的成员函数,无形参。类的成员函数,无形参。 经重载后,经重载后,表达式表达式 U oprd 相当于相当于 oprd.operator U( )l后置单目运算符后置单目运算符 +和和

10、- 如果要重载如果要重载 +或或-为类成员函数,使之能够为类成员函数,使之能够实现表达式实现表达式 oprd+ 或或 oprd- ,其中,其中 oprd 为为A类对象,则类对象,则 +或或- 应被重载为应被重载为 A 类的类的成员函数,且具有一个成员函数,且具有一个 int 类型类型形参形参。 经重载后,表达式经重载后,表达式 oprd+ 相当于相当于 oprd.operator +(0)补充:补充:l运算符前置运算符前置+和后置和后置+重载为时钟类的成员函数。重载为时钟类的成员函数。l前置单目运算符,重载函数没有形参,对于后置单目前置单目运算符,重载函数没有形参,对于后置单目运算符,重载函数

11、需要有一个整型形参。运算符,重载函数需要有一个整型形参。l操作数是时钟类的对象。操作数是时钟类的对象。l实现时间增加实现时间增加1秒钟。秒钟。#includeclass Clock /时钟类声明时钟类声明public:/外部接口外部接口Clock(int NewH=0, int NewM=0, int NewS=0);void ShowTime( );void operator +( ); /前置单目运算符重载前置单目运算符重载void operator +(int); /后置单目运算符重载后置单目运算符重载private:/私有数据成员私有数据成员int Hour, Minute, Seco

12、nd;void Clock:operator +( )/前置单目运算符重载函数前置单目运算符重载函数Second+;if(Second=60) Second=Second-60;Minute+;if(Minute=60) Minute=Minute-60;Hour+;Hour=Hour%24;cout=60) Second=Second-60;Minute+;if(Minute=60) Minute=Minute-60;Hour+;Hour=Hour%24;coutClock+: ;/其它成员函数的实现略其它成员函数的实现略void main( )Clock myClock(23,59,59)

13、;coutFirst time output:;myClock.ShowTime( );myClock+;myClock.ShowTime( );+myClock;myClock.ShowTime( );程序运行结果为:程序运行结果为:First time output:23:59:59Clock+: 0:0:0+Clock: 0:0:16.1.3 6.1.3 用友元函数重载运算符用友元函数重载运算符friend type operator (friend type operator (参数表参数表););注意友元函数不属于任何类,它没有注意友元函数不属于任何类,它没有thisthis指针指针

14、,这与成员,这与成员函数完全不同。若运算符是一元的,则参数表中有一个操作数;函数完全不同。若运算符是一元的,则参数表中有一个操作数;若运算符是二元的,则参数表中有两个操作数。也就是说在用若运算符是二元的,则参数表中有两个操作数。也就是说在用友元定义重载运算符时,所有的操作数均需要用参数来传递。友元定义重载运算符时,所有的操作数均需要用参数来传递。友元运算符函数与成员运算符函数的主要区别在其参数个数不友元运算符函数与成员运算符函数的主要区别在其参数个数不同同。当运算符的左操作数是一个常数时,就不能利用。当运算符的左操作数是一个常数时,就不能利用thisthis指针,指针,应当用友元函数重载。应当

15、用友元函数重载。友元运算符函数的定义如下:友元运算符函数的定义如下:type type operator (operator (参数表参数表) ) / / 运算符处理程序代码运算符处理程序代码 例题例题【例【例6.36.3】用友元函数重载运算符一用友元函数重载运算符一 【例【例6.46.4】用友元函数重载运算符实现两字符串加法用友元函数重载运算符实现两字符串加法 参看教材的说明参看教材的说明【例【例6.56.5】用重载运算符的方法进行复数运算用重载运算符的方法进行复数运算 1运算符!和运算符!和的重载的重载【例【例6.66.6】运算符!和】运算符!和的重载的重载2前自增和后自增运算符前自增和后

16、自增运算符+的重载的重载前自增运算符前自增运算符+和后自增运算符和后自增运算符+重载的语法重载的语法 operator+(); /operator+(); /前前 operator+(operator+(intint); /); /后后【例【例6.76.7】用成员函数重载前自增和后自增运算符。】用成员函数重载前自增和后自增运算符。【例【例6.86.8】用友元重载前自增和后自增用友元重载前自增和后自增 3运算符运算符-的重载的重载-运算符是成员访问运算符,这种一元的运算符只能被重载为运算符是成员访问运算符,这种一元的运算符只能被重载为成员函数,成员访问运算符成员函数,成员访问运算符-函数重载的一

17、般形式为:函数重载的一般形式为:【例例6.96.9】重载】重载-运算符。运算符。在正常的情况下,系统会为每一个类自动生成一在正常的情况下,系统会为每一个类自动生成一个默认的完成上述功能的赋值运算符,当然,这种个默认的完成上述功能的赋值运算符,当然,这种赋值只限于同一个类类型说明的对象之间赋值,相赋值只限于同一个类类型说明的对象之间赋值,相当于浅拷贝构造函数。当于浅拷贝构造函数。【例例6.106.10】赋值运算符的重载一。】赋值运算符的重载一。【例例6.116.11】赋值运算符的重载二。】赋值运算符的重载二。【例例6.126.12】赋值运算符的重载三。】赋值运算符的重载三。 6.2 6.2 虚函

18、数虚函数 指向基类对象的指针都可以指向它的公有派生类对象,若指向基类对象的指针都可以指向它的公有派生类对象,若试图指向它的私有派生类对象是被禁止的。试图指向它的私有派生类对象是被禁止的。不能将一个声明为不能将一个声明为指向派生类对象的指针指向其基类的一个对象。指向派生类对象的指针指向其基类的一个对象。 声明为指向基类对象的指针,当它指向公有派生类对象时,声明为指向基类对象的指针,当它指向公有派生类对象时,只能利用它来直接访问派生类中从基类继承来的成员,不能直只能利用它来直接访问派生类中从基类继承来的成员,不能直接访问公有派生类中特定的成员。接访问公有派生类中特定的成员。若想访问其公有派生类的特

19、若想访问其公有派生类的特定成员,可以将基类指针显式类型转换为派生类指针来实现。定成员,可以将基类指针显式类型转换为派生类指针来实现。 【例【例6.146.14】为什么要引入虚函数为什么要引入虚函数6.2.2 6.2.2 虚函数的定义与使用虚函数的定义与使用 1 1虚函数的定义虚函数的定义 虚函数是引入了派生概念后,用来表现基类和派虚函数是引入了派生概念后,用来表现基类和派生类的成员函数之间的一种关系的。生类的成员函数之间的一种关系的。虚函数定义是在虚函数定义是在基类中进行的(基类中进行的(virtualvirtual), ,虚函数提供了一种接口界虚函数提供了一种接口界面。在基类中的某个成员函数

20、被声明为虚函数后,此面。在基类中的某个成员函数被声明为虚函数后,此虚函数就可以在一个或多个派生类中被重新定义。虚函数就可以在一个或多个派生类中被重新定义。在在派生类中重新定义虚函数时,都必须与基类中的派生类中重新定义虚函数时,都必须与基类中的原型原型完全相同完全相同。 虚函数是一种虚函数是一种非静态非静态的成员函数,说明虚函数的的成员函数,说明虚函数的方法如下:方法如下: virtual virtual 类型函数名(参数表)类型函数名(参数表)使用虚函数时应注意以下几点使用虚函数时应注意以下几点(1):(1): (1) (1) 虚函数是在基类和派生类中说明相同而实现不同的成员函数,在虚函数是在

21、基类和派生类中说明相同而实现不同的成员函数,在派生类中重新定义基类中的虚函数时,可以不加派生类中重新定义基类中的虚函数时,可以不加virtualvirtual,因为因为虚特虚特性可以传递性可以传递,但,但函数原型必须与基类中的完全相同,否则会丢失虚特函数原型必须与基类中的完全相同,否则会丢失虚特性。性。(2) (2) 基类中说明的虚函数具有下传给派生类的性质。基类中说明的虚函数具有下传给派生类的性质。(3) (3) 析构函数可以是的虚函数,但构造函数则不能是虚函数。析构函数可以是的虚函数,但构造函数则不能是虚函数。一般地一般地讲,若某类中定义有虚函数,则其析构函数也应当说明为虚函数。特讲,若某

22、类中定义有虚函数,则其析构函数也应当说明为虚函数。特别是在析构函数需要完成一些有意义的操作别是在析构函数需要完成一些有意义的操作比如释放内存时,尤比如释放内存时,尤其应当如此。其应当如此。(4) (4) 在类体系中访问一个虚函数时,应使用指向基类的指针或对基类在类体系中访问一个虚函数时,应使用指向基类的指针或对基类的引用,以满足运行时多态性的要求的引用,以满足运行时多态性的要求。当然也可以像调用普通成员函。当然也可以像调用普通成员函数那样利用对象名来调用一个虚函数这时会丢失虚特性。数那样利用对象名来调用一个虚函数这时会丢失虚特性。(5) (5) 在派生类中重新定义虚函数时,在派生类中重新定义虚

23、函数时,必须保证派生类中该函数的返必须保证派生类中该函数的返回值和参数与基类中的说明完全一致,回值和参数与基类中的说明完全一致,否则就属于重载(如果参数否则就属于重载(如果参数不同)或是一个错误(参数相同,仅返回值不同)。不同)或是一个错误(参数相同,仅返回值不同)。(6) (6) 若在派生类中没有重新定义虚函数,则派生类的对象将使用其若在派生类中没有重新定义虚函数,则派生类的对象将使用其基类中的虚函数代码。基类中的虚函数代码。(7) (7) 虚函数必须是类的一个成员函数,不能是友元,但它可以是另虚函数必须是类的一个成员函数,不能是友元,但它可以是另一个类的友元。另外,一个类的友元。另外,虚函

24、数不能是一个静态成员函数。虚函数不能是一个静态成员函数。(8)(8)构造函数只能用构造函数只能用inlineinline进行修饰,不能是虚函数进行修饰,不能是虚函数。 (9) (9) 一个类的虚函数仅对派生类中重定义的函数起作用,对其它函一个类的虚函数仅对派生类中重定义的函数起作用,对其它函数没有影响。在基类中使用虚函数保证了通过指向基类对象的指针数没有影响。在基类中使用虚函数保证了通过指向基类对象的指针调用基类的一个虚函数时,调用基类的一个虚函数时,C+C+系统对该调用进行系统对该调用进行动态绑定动态绑定,而使用,而使用普通函数则是静态绑定。普通函数则是静态绑定。使用虚函数时应注意以下几点使

25、用虚函数时应注意以下几点(2):(2): (10)(10) 使用虚函数方法后,不得再使用类作用域区分使用虚函数方法后,不得再使用类作用域区分符强制指明要引用的虚函数。因为此法将破坏多态性符强制指明要引用的虚函数。因为此法将破坏多态性而使编译器无所适从。而使编译器无所适从。(11)(11) 若派生类中没有再定义基类中已有的虚函数,若派生类中没有再定义基类中已有的虚函数,则指向该类对象的指针或引用名引用虚函数时总是引则指向该类对象的指针或引用名引用虚函数时总是引用距离其最近的一个基类中的虚函数。用距离其最近的一个基类中的虚函数。(12)(12) 若在基类的构造(析构)函数中也引用虚函数,若在基类的

26、构造(析构)函数中也引用虚函数,则所引用的只能是本类的虚函数,因为此时派生类中则所引用的只能是本类的虚函数,因为此时派生类中的构造(析构)函数的执行尚未完成。的构造(析构)函数的执行尚未完成。使用虚函数时应注意以下几点使用虚函数时应注意以下几点(3):(3): 2. 2. 虚函数与重载函数的关系虚函数与重载函数的关系(1) (1) 重载函数要求函数有相同的返回值类型和函数名重载函数要求函数有相同的返回值类型和函数名称,并有不同的参数序列;而虚函数则要求这三项称,并有不同的参数序列;而虚函数则要求这三项(函数名、返回值类型和参数序列)完全相同;(函数名、返回值类型和参数序列)完全相同;(2) (

27、2) 重载函数可以是成员函数或友员函数,而虚函数重载函数可以是成员函数或友员函数,而虚函数只能是成员函数;只能是成员函数;(3) (3) 重载函数的调用是以所传递参数序列的差别作为重载函数的调用是以所传递参数序列的差别作为调用不同函数的依据;虚函数是根据对象的不同去调调用不同函数的依据;虚函数是根据对象的不同去调用不同类的虚函数;用不同类的虚函数;(4) (4) 虚函数在运行时表现出多态功能,这是虚函数在运行时表现出多态功能,这是C+C+的精的精髓;而重载函数则在编译时表现出多态性。髓;而重载函数则在编译时表现出多态性。 3 3虚函数的使用虚函数的使用 定义一个基类类型的对象指针或引用便可使其

28、在需要定义一个基类类型的对象指针或引用便可使其在需要时指向相应的类对象,并用此指针或引用去引用该对象时指向相应的类对象,并用此指针或引用去引用该对象所对应的类中已被所对应的类中已被“虚拟化虚拟化”的函数,从而可以实现真的函数,从而可以实现真正的运行时的多态性。正的运行时的多态性。【例【例6.166.16】虚函数的使用举例。虚函数的使用举例。【例【例6.176.17】异质链表的实现】异质链表的实现:有三个类:有三个类studentstudent、teacherteacher、staffstaff,再定义一个链表类,此类用来存放这再定义一个链表类,此类用来存放这几个不同类的对象;并将链表几个不同类

29、的对象;并将链表listlist声明为所有这些类的声明为所有这些类的友元,使它可以访问它们的私有成员。友元,使它可以访问它们的私有成员。 4 4在构造函数和析构函数中调用虚函数在构造函数和析构函数中调用虚函数在构造函数和析构函数中调用虚函数时,在构造函数和析构函数中调用虚函数时,采用静态联编,即它们所调用的虚函数是自己采用静态联编,即它们所调用的虚函数是自己的类或基类中定义的函数而不是在任何派生类的类或基类中定义的函数而不是在任何派生类中重定义的函数。同样,使用对象调用虚函数中重定义的函数。同样,使用对象调用虚函数也采用静态联编。也采用静态联编。【例【例6.186.18】在构造函数中调用虚函数

30、在构造函数中调用虚函数5 5空的虚函数空的虚函数 派生类并不一定必须实现基类中的虚派生类并不一定必须实现基类中的虚函数,如果派生类想通过虚函数机制存取虚函函数,如果派生类想通过虚函数机制存取虚函数,则必须建立一条从基类到派生类的虚函数数,则必须建立一条从基类到派生类的虚函数路径。许多没有使用虚函数的中间类也必须声路径。许多没有使用虚函数的中间类也必须声明该函数,以保证其后的派生类能使用该虚函明该函数,以保证其后的派生类能使用该虚函数。可以通过声明空函数来达到此目的。数。可以通过声明空函数来达到此目的。 【例【例6.196.19】空虚函数空虚函数 6.3 6.3 纯虚函数和抽象类纯虚函数和抽象类

31、6.3.1 6.3.1 纯虚函数的概念纯虚函数的概念 如果基类只表达一些抽象的概念,而并不与具体的对如果基类只表达一些抽象的概念,而并不与具体的对象相联系,但它又必须为它的派生类提供一个公共的界面,象相联系,但它又必须为它的派生类提供一个公共的界面,在这种情况下,可以将基类中的虚函数定义成纯虚函数。在这种情况下,可以将基类中的虚函数定义成纯虚函数。纯虚函数是一种没有具体实现的特殊的虚函数。纯虚函数是一种没有具体实现的特殊的虚函数。一个基类一个基类中有一个纯虚函数时,则在它的派生类中至少有一个虚函中有一个纯虚函数时,则在它的派生类中至少有一个虚函数,否则纯虚函数是无意义的。数,否则纯虚函数是无意

32、义的。纯虚函数的定义格式如下:纯虚函数的定义格式如下: virtual virtual 类型类型( (函数名函数名)()(参数表参数表)=0)=0; 由于纯虚函数所在的类中没有它的定义,在该类的构由于纯虚函数所在的类中没有它的定义,在该类的构造函数和析构函数中不允许调用纯虚函数,否则会导致程造函数和析构函数中不允许调用纯虚函数,否则会导致程序运行错误。但其它成员函数可以调用纯虚函数。序运行错误。但其它成员函数可以调用纯虚函数。6.3.2 6.3.2 抽象类的概念抽象类的概念 1 1抽象类和具体类的概念抽象类和具体类的概念 如果一个类至少有一个纯虚函数,那么就称该类为如果一个类至少有一个纯虚函数

33、,那么就称该类为抽象类抽象类。能够建立实例化对象的类称为具体类,也就。能够建立实例化对象的类称为具体类,也就是不含纯虚函数的类为具体类。是不含纯虚函数的类为具体类。 抽象类的主要作用是为其所组织的继承层次结构抽象类的主要作用是为其所组织的继承层次结构提供一个公共的基类,它刻划了公有行为的特征,其提供一个公共的基类,它刻划了公有行为的特征,其它类可以从它这里继承和实现接口,纯虚函数的实现它类可以从它这里继承和实现接口,纯虚函数的实现由其具体的派生类来提供。由其具体的派生类来提供。2 2对抽象类的几点规定对抽象类的几点规定(1) (1) 抽象类只能作为基类来派生新类,抽象类只能作为基类来派生新类,

34、不能建立不能建立抽象类的对象。抽象类的对象。(2) (2) 抽象类抽象类不能不能用作参数类型、函数返回值类型、用作参数类型、函数返回值类型、或显式转换的类型。或显式转换的类型。(3) (3) 可以声明指向抽象类的指针和引用,此指针可以声明指向抽象类的指针和引用,此指针可以指向它的公有派生类,进而实现多态性。可以指向它的公有派生类,进而实现多态性。(4) (4) 从一个抽象类派生的从一个抽象类派生的具体类具体类必须提供纯虚函必须提供纯虚函数的实现代码。数的实现代码。(5) (5) 如果基类中含有纯虚函数,而其派生类却并如果基类中含有纯虚函数,而其派生类却并没有重新定义这些纯虚函数的覆盖成员函数,

35、那么这没有重新定义这些纯虚函数的覆盖成员函数,那么这个派生类也是抽象类,因此也不能用来定义对象。但个派生类也是抽象类,因此也不能用来定义对象。但此情况不会影响以后的派生类。此情况不会影响以后的派生类。(6) (6) 含有纯虚函数的类中可以包含非纯虚函数,但这含有纯虚函数的类中可以包含非纯虚函数,但这些虚函数只能通过其派生类的对象才能被引用。些虚函数只能通过其派生类的对象才能被引用。(7) (7) 如果派生类中给出了基类所有纯虚函数的实现,如果派生类中给出了基类所有纯虚函数的实现,则该派生类不再是抽象类。则该派生类不再是抽象类。(8)(8)在成员函数内可以调用纯虚函数(程序员很少这样在成员函数内

36、可以调用纯虚函数(程序员很少这样做),但在构造函数或析构函数内调用纯虚函数将导做),但在构造函数或析构函数内调用纯虚函数将导致程序连接有错误,因为没有为纯虚函数定义代码。致程序连接有错误,因为没有为纯虚函数定义代码。3 3抽象类举例抽象类举例【例【例6.206.20】计算各类形状的总面积。计算各类形状的总面积。6.4 6.4 虚析构函数虚析构函数(1)(1)6.4 6.4 虚析构函数虚析构函数(2)(2)【例【例6.21】虚析构函数的使用虚析构函数的使用。 习习 题题 (1) (1)1. 1. 虚函数和重载设计方法上有何相同和不同之处?虚函数和重载设计方法上有何相同和不同之处?2. 2. 什么是纯虚函数?什么是抽象类?什么是纯虚函数?什么是抽象类?抽象类的特性抽象类的特性是什么?是什么?3. 3. 给字符串类定义下列重载运算符函数:给字符串类定义下列重载运算符函数:(1) (1) 赋值运算符赋值运算符= =(2) (2

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论