VC程序设计核心——类与对象学习教案_第1页
VC程序设计核心——类与对象学习教案_第2页
VC程序设计核心——类与对象学习教案_第3页
VC程序设计核心——类与对象学习教案_第4页
VC程序设计核心——类与对象学习教案_第5页
已阅读5页,还剩106页未读 继续免费阅读

下载本文档

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

文档简介

1、会计学1VC程序设计程序设计(chn x sh j)核心核心类与对象类与对象第一页,共111页。2第1页/共110页第二页,共111页。3第2页/共110页第三页,共111页。4 抽象是指从具体的实例中抽取出来共同的性质并加以描述的过程(guchng),它忽略了一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。 第3页/共110页第四页,共111页。5第4页/共110页第五页,共111页。6E继承是一种联结(linji)类与类之间的层次模型,它允许和鼓励类的重用,提供了一种明确表达共性的方法。E一个新类可以从现有的类中派生,这个过程称为类继承 E继承性很好地解决了软件的

2、可重用问题 第5页/共110页第六页,共111页。7E多态性指的是同一消息被不同的对象接收后被解释为不同含义的能力,也就是一个接口名称具有(jyu)多种功能。E E多态性语言具有(jyu)语言灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名的问题。第6页/共110页第七页,共111页。8E 1VC提供面向对象的完整语法与语义 E 2. VC还是一种结构化的程序设计(chn x sh j)语言E 3VC中的MFC是理解面向对象语法与语义E 的最好平台第7页/共110页第八页,共111页。9 面向对象编程的好处最明显的是使代码的可重用性大大提高,使程序员摆脱了重复性的劳动。 面向

3、对象编程中的对象比较独立,它给外界(wiji)提供了统一的接口,当对象一旦建立,就可以重复使用 。 采用面向对象编程的好处就是代码的可扩充性。 第8页/共110页第九页,共111页。10第9页/共110页第十页,共111页。111结构体 VC不仅提供了大量预先定义的数据类型,而且还支持自定义的数据类型。 结 构 就 是 把 相 互 关 联 的 一 些 基 本(jbn)数据类型的元素组成一个新的独立统一体。 第10页/共110页第十一页,共111页。12 【例3-1】 定义一个职工(zhgng)Employee结构数据类型,它包括姓名、工资、地址、移动电话。struct Employeechar

4、 name9;float salary;char address40;char mobile12; ;定义一个结构体,事实上是定义了一种数据类型(lixng),程序并不会给类型(lixng)分配内存,内存分配是发生在结构体变量上第11页/共110页第十二页,共111页。13【例3-2】 定义一个具体(jt)职工EmployeeA,并对该职工进行赋值。程序的主文件名为。第12页/共110页第十三页,共111页。14程序的运行结果是:要想拜谒(biy)她,请到峨眉山上或直接传呼 第13页/共110页第十四页,共111页。152类类是从一个个具体的事物中把共同特征抽取出来形成(xngchng)的一个

5、概念,它反映了事物之间的共性 在C+中,在类的定义中,不仅有反映事物属性的成员变量,还有反映属性操作的成员函数。类一种自定义数据类型 。第14页/共110页第十五页,共111页。16在C+中类的定义方式为:class 类名private: 私有数据及成员函数;protected: 保护(boh)数据及成员函数;public: 公有数据及成员函数;;第15页/共110页第十六页,共111页。17Eclass是类定义符,类名是一种标识符,它的命名规则与变量名的命名规则相同。一对花括号(kuho)内是类的说明部分,说明该类的成员。类的成员包括成员变量和成员函数两部分。E上述在类的成员变量和成员函数前

6、面出现的关键字public(公有)、private(私有)或protected(保护)表示成员的访问属性。在类中声明的成员变量若不特别指明,都被视为私有类型。私有类型的数据只允许类本身声明的函数对其进行存取,而类外部的任何函数都不能访问。公有类型的成员可以被任何函数来访问,它们是类与外部的接口。 第16页/共110页第十七页,共111页。18第17页/共110页第十八页,共111页。19第18页/共110页第十九页,共111页。20第19页/共110页第二十页,共111页。21第20页/共110页第二十一页,共111页。22第21页/共110页第二十二页,共111页。23 由于(yuy)CTi

7、me类是MFC中的一个类,在使用该类库中的类时,必须在类的定义文件开始加上#include 语句,并对VC当前开发的工程进行一些设置(点击菜单Projects|Setting,打开General选项卡,在Microsoft Foundation Classes列表框中选择Use MFC in a Shared DLL)。 第22页/共110页第二十三页,共111页。24第23页/共110页第二十四页,共111页。25第24页/共110页第二十五页,共111页。26第25页/共110页第二十六页,共111页。27第26页/共110页第二十七页,共111页。28第27页/共110页第二十八页,共1

8、11页。29 CwinApp是Windows的一个应用程序类,它里面的一些公有(gngyu)的成员变量在程序中经常要使用。m_pszAppName:应用程序的名称(包含路径)。m_hInstance:应用程序的当前实例。m_hPrevInstance:应用程序的前一个实例。m_nCmdShow:应用程序主窗口的最初何显示方式(最大化、最小化等)。m_pMainWnd:指向应用程序主窗口的指针变量。m_pszExeName:应用程序的模块名称(不包含路径)。第28页/共110页第二十九页,共111页。30 当成员函数的函数体代码较短时,可以在定义类时直接(zhji)定义成员函数,即在类内定义成员

9、函数。但当成员函数函数体较复杂时,可以在类体外定义成员函数,但必须在类内对成员函数进行声明。 1类的普通(ptng)成员函数 【例3-9】 在前面定义的职工TEmployee类中有一个输入职工姓名、工资等属性的成员函数input(),通过它实现职工对象的初始化。另外还有一个显示职工信息的成员函数diplay(),这些函数在类体外进行定义: 第29页/共110页第三十页,共111页。31class TEmployeepublic:void input(char *name,float salary,char *address, char *mobile); void display();priv

10、ate:char m_name9;void TEmployee:input(char *name,float salary,char *address, char *mobile)strcpy(m_name,name); /字符串赋值必须(bx)通过字符串拷贝来实现m_salary=salary;strcpy(m_address,address);strcpy(m_mobile,mobile); 第30页/共110页第三十一页,共111页。32void TEmployee:display()coutName Is m_nameendl;coutSalary Is m_salaryendl;co

11、utAddress Is m_addressendl;coutmobile Is m_mobileendl; 说明:在类体外定义成员函数时必须使用作用域运算符“:”来指明成员函数所属的类,在类体内访问成员函数时,若未指明所属的类,则默认(mrn)是这个类的成员函数,若要访问该类之外的其它类的成员函数,则必须指名该成员函数所属的类。第31页/共110页第三十二页,共111页。33 静态成员函数仅属于一个类而不属于该类的任何(rnh)对象,因此它不通过对象直接调用,而是与类相联系的。静态成员函数中没有this指针,并且静态成员函数中只能访问静态成员变量,在类外调用静态成员函数时应使用以下方式: 类

12、名:静态成员函数名(参数列表);第32页/共110页第三十三页,共111页。34#include #include class TStudentprivate:char m_Name6;static int m_ClassMoney; /m_ClassMoney为静态(jngti)成员变量,保存班费public:void InitStudent(char *);void ExpendMoney(int); static void ShowMoney();/静态(jngti)成员函数;第33页/共110页第三十四页,共111页。35第34页/共110页第三十五页,共111页。36void mai

13、n()TStudent stu3;/定义三个学生(xu sheng)stu0.InitStudent(marry); stu1.InitStudent(sunny);stu2.InitStudent(jahn);stu0.ExpendMoney(100);stu0.ShowMoney();/作用等同于TStudent:ShowMoney();stu1.ExpendMoney(100);stu1.ShowMoney();/作用等同于TStudent:ShowMoney();stu2.ExpendMoney(100);stu2.ShowMoney();/作用等同于TStudent:ShowMone

14、y();第35页/共110页第三十六页,共111页。37 从形式上看,虚函数(hnsh)是在一个函数(hnsh)的定义前面加上关键词virtual而构成的函数(hnsh)。将函数(hnsh)定义为虚函数(hnsh)后,可以达到动态联编的效果 第36页/共110页第三十七页,共111页。38class TPoint /定义一个点类private :float x, y ; /x为横坐标,y为纵坐标public :void Point (float i , float j) x=i ; y=j; /构造函数virtual float area ( ) return 0.0 ; /求面积(min j

15、)的虚函数; 第37页/共110页第三十八页,共111页。39CString的主要成员函数如下:(1) GetLength:返回CString对象中的字符数。(2) IsEmpty:测试一个CString对象是否空。(3) Empty:将一个字符数的长度(chngd)强制为0。(4) GetAt:返回给定位置上的字符。(5) SetAt:设置给定位置上的字符。(6) Mid:提取一个字符串的中间部分。 第38页/共110页第三十九页,共111页。40请看下例:C(7) Left:提取一个字符串的左边部分。C(8) Right:提取一个字符串的右边部分。C(9) MakeUpper:将字符串中的

16、所有字符转换为大写字符。C(10) MakeLower:将字符串中的所有字符转换为小写字符。C(11) Find:在一个较大的字符串中查找某一个字符串。C(12) GetBuffer:返回(fnhu)一个指向CString对象的指针。 第39页/共110页第四十页,共111页。41#include #include /CString的头文件void main()CString Str1=VC+实用教程; CString Str2=出版商:电子工业(gngy)出版社n; CString Str3=Str1+Str2; CString Str4=出版社;coutStr3.GetBuffer(0);

17、/取字符串的首地址 第40页/共110页第四十一页,共111页。42比较(bjio)c*c*cif(Str1.Compare(Str2) /字符串比较cout字符串Str1与Str2不相同(xin tn)n;Str3=Str1.Left(2)+Str1.Right(4); /提取字符串coutStr3.GetBuffer(0)0) /利用成员函数Find查找子串cout在Str2中找到子串Str4n;程序运行结果为:VC+实用教程出版商:电子(dinz)工业出版社字符串Str1与Str2不相同VC教程在Str2中找到子串Str4第41页/共110页第四十二页,共111页。43请看下例:第42页

18、/共110页第四十三页,共111页。44#include class circlepublic: void set(int r) radius = r ; float area();private :float radius;float circle:area() return (PI*radius*radius); 第43页/共110页第四十四页,共111页。45void main()int radius ; circle MyCircle ;coutradius;MyCircle.set(radius); /正确,因为成员函数set()为公有成员cout该圆的面积为:()成员函数),它是隐

19、式调用,即在一个新对象建立时(包含两种情况:一种是在对象的声明语句中,另一种是用new函数建立新的动态对象时),该对象所隶属类的构造函数自动被调用。 第52页/共110页第五十三页,共111页。54第53页/共110页第五十四页,共111页。55第54页/共110页第五十五页,共111页。56第55页/共110页第五十六页,共111页。57第56页/共110页第五十七页,共111页。58程序运行结果为:Ex1 类的对象建立,其构造函数被调用Ex2 类的对象建立,其构造函数被调用class Exl: 10class Ex2: 25Ex2类的对象撤消(chxio),其析构函数被调用Ex1类的对象撤

20、消(chxio),其析构函数被调用第57页/共110页第五十八页,共111页。59第58页/共110页第五十九页,共111页。603.4.1 类与类之间的四种关系3.4.2 继承的概念 3.4.3 派生类的声明 3.4.4 基类成员(chngyun)的访问控制 3.4.5 派生与继承的应用 第59页/共110页第六十页,共111页。61 是封装了事物(shw)属性和方法的同类对象的集合。 类UML(unified model language,统一建模语言)认为,类之间主要(zhyo)存在四种关系。1关联(Association)关系 关联关系表示两个类之间存在某种语义上的联系, 即与该关联连

21、接的类的对象之间具有一定的语义连接关系,该关系表达了类之间的一种相关性。第60页/共110页第六十一页,共111页。622依赖(yli)(Dependency)关系 依赖关系描述的是两个类之间的语义上的连接关系,它是一种(y zhn)“Use-A”关系。假设有两个元素A与B,如果修改元素A的定义可能会引起对另一个元素B的定义的修改,则称元素B依赖于A。 3聚合(jh)(Aggregation)关系 聚合关系是一种“Has-A”关系,它体现的是类之间的一种整体与部分的关系。例如汽车包括四个轮子和一个发动机等。 第61页/共110页第六十二页,共111页。634泛化(Generalization

22、)关系(gun x) 泛化关系是一种“Is-A”关系,它描述的是类之间的“一般”与“特殊”的关系。具有共同特性(txng)的元素可以抽象为一般类,并通过增加其内涵,进一步抽象成特殊类。该关系可以将类组成一种有层次、有分类的结构。例如:狗是一种哺乳动物,哺乳动物是一种动物等。在VC中建立类之间的泛化关系采用的是继承机制。第62页/共110页第六十三页,共111页。64 继承是描述类与类之间关系的一个概念(ginin),它提高了代码的重用性,使得程序更加模块化,便于程序更简单而又准确地描述事物。 继承关系可以用由派生类指向基类的箭头表示, 如图所示: 交通工具飞机汽车火车轿车卡车面包车第63页/共

23、110页第六十四页,共111页。65单继承中派生类的声明格式(g shi)为: class 派生类类名:访问控制限定符 基类名;其中访问控制限定符号可以是public(公有派生)、protected (保护派生)和private(私有派生) 。 【例3-17】一个派生类的声明实例。如果交通工具用前面讲的类TVehicle来抽象表示,汽车用类TCar来抽象表示的话(dehu),那么汽车从交通工具继承而来(或交通工具派生汽车的)的语义表示成C+语言的语法描述为:第64页/共110页第六十五页,共111页。66class TCar: public TVehiclepublic:void Initia

24、lize(int wheels,float weight,int passenger=4);GetPassenger(void);private:int m_passenger;第65页/共110页第六十六页,共111页。67 我们可以根据下表中的继承成员访问控制规则来决定使用哪种访问方式更合理,不同的访问控制,决定了基类可以被派生类所访问的“开放”程度。 第66页/共110页第六十七页,共111页。68表3.1 继承(jchng)成员访问控制规则继承访问控制基类成员访问控制在派生类中的访问控制publicpublicpublicprotectedprotectedprivate不可访问pro

25、tectedpublicprotectedprotectedprotectedprivate不可访问privatepublicprivateprotectedprivateprivate不可访问第67页/共110页第六十八页,共111页。69【例3-19】一个使用类的继承实例(shl)。主文件为。#include class TVehicle /交通工具类的声明public :void Initialize(int wheels,float weight);int GetWheels(void) return m_wheels;float GetWeight(void)return m_wei

26、ght;private:int m_wheels; /轮子(ln zi)float m_weight; /载重;第68页/共110页第六十九页,共111页。70void TVehicle:Initialize(int wheels,float weight)m_wheels=wheels; m_weight=weight;class TCar: public TVehicle/汽车类从交通工具类公有(gngyu)派生public:void Initialize(int wheels,float weight,int passenger);int GetPassenger(void) retur

27、n m_passenger;private:int m_passenger; /乘客数;void TCar:Initialize(int wheels,float weight,int passenger=4)TVehicle:Initialize(wheels,weight); /调用父类的函数进行初始化第69页/共110页第七十页,共111页。71第70页/共110页第七十一页,共111页。72程序运行结果为:交通工具(jiotng gngj)轮子的个数是:4交通工具(jiotng gngj)轮子的载重为:6汽车的轮子、载重和乘客数为:1 2 4第71页/共110页第七十二页,共111页。

28、733.5.1 多态性概述3.5.2 多态性的类型(lixng) 3.5.3 编译时多态性的两种方式3.5.4 运行时多态性的实现条件3.5.5 纯虚函数与抽象类 3.5.6 * 使用虚函数的好处习题第72页/共110页第七十三页,共111页。74 在VC中,这种同一符号或名字在不同情况下表现为不同的语义现象(xinxing)称为多态性。 严格地讲,在VC中,不同的类可以有语义相同(xin tn)的函数,这些函数在概念上是相似的,但对应各自的类来说,其实现是不同的,因而对象在接收到同样的函数调用时所引发的行为有可能是不同的,这一功能称为多态性。直观地讲就是“一个名称,多个函数”。第73页/共1

29、10页第七十四页,共111页。75 程序设计的多态性有两种形式:编译(biny)时的多态性和运行时的多态性。 多态性的实现与联编有关。将一个函数的调用与其相应的函数体代码相链接(lin ji)的过程,称为函数联编。C+中有两种类型的联编:静态联编和动态联编。第74页/共110页第七十五页,共111页。76 静态联编是指在调用同名函数(即重载函数)时,编译器将根据调用时所使用的实际参数个数、类型的不同确定应该(ynggi)调用哪一个函数的实现,它是在程序编译阶段就确定下来的多态性。静态联编通过使用重载(overload)机制来获得,重载机制包括函数重载和运算符重载。 动态联编是在程序的运行阶段根

30、据当时的情况来确定应该调用哪个同名(tngmng)函数的实现。动态联编主要通过继承与虚函数两者结合来实现的。 第75页/共110页第七十六页,共111页。77 静态联编的代码链接工作是在编译时完成的,所以运行时不需要额外时间来做这些工作,因此静态联编的代码效率较高。 动态联编将函数调用的链接时间后移到代码执行的时候,这必然使函数调用时间开销增加,效率降低,但大大增强了语言的灵活性。程序员可以根据(gnj)实际情况需要来决定使用哪一种联编方式,从而兼顾代码的高效性和灵活性。 静态(jngti)联编与动态联编各有优缺点:第76页/共110页第七十七页,共111页。781函数重载 两个以上的函数,取

31、相同的函数名称(mngchng),但是形参个数或者类型不同,编译器根据实参和形参的类型和个数选择最匹配的函数,来自动地确定调用哪一个函数,这就是函数的重载。函数重载包括普通成员函数重载和类的成员函数重载 ,下面给出相应的实例。 【例3-20】 普通函数重载的例子。给函数add()定义多个函数来实现,该函数的功能是求和,可以求两个整型数之和,两个浮点数之和,也可以求三个双精度浮点数之和,每种实现对应着一个函数体,这些函数的名字相同,但是(dnsh)函数的参数个数或类型不同,这就是函数重载。在VC+中,函数可以共享同一个名字,只是这些同名函数的参数表有所不同。程序的主文件为。第77页/共110页第

32、七十八页,共111页。79#includeint add(int a,int b)return a+b; float add(float x, float y)return x+y; void add(double a,double b,double c)couta+b+cendl; void main() int m=1,n=2; float x=1.2,y=2.3; double a=2.0,b=3.0,c=2.5; coutadd(m,n)endl; /因为(yn wi)m与n为int型,故调用的是第一个add函数 coutadd(x,y)endl; /因为(yn wi)x与y为floa

33、t型,故调用的是第二个add函数 add(a,b,c); /因为(yn wi)a、b、c为double,且包含三个参数型,故调用的是第三 个add函数第78页/共110页第七十九页,共111页。80 从程序的运行结果(ji gu)来看add(m,n)是调用了int add(int a,int b)函数;add(x,y)调用了函数float add(float x, float y);add(a,b,c)调用了void add(double a,double b,double c)函数。这些函数可以同名,同名的函数为重载函数。程序的运行(ynxng)结果是:3第79页/共110页第八十页,共11

34、1页。81 注意:(1)函数重载时,函数声明必须能互相区别,即函数参数个数或参数类型必须有所不同,如果只有函数的返回值不同,不能区分重载函数;(2)函数功能一般相类似,本质上有区别的函数,最好不要重载;(3)不同参数传递方式无法区别重载函数。例如(lr):int add(int a,int b); int add(int &a,int &b); 这两个函数不能作为重载函数,编译时会出错。 第80页/共110页第八十一页,共111页。82【例3-21】类的成员(chngyun)函数重载的例子。 类的成员(chngyun)函数重载的最典型的情况在类的构造函数的重载。MFC类库中有一

35、个点类CPoint,查看MSDN的说明,知道它有多个构造函数,下面为其中的构造函数的原型说明:CPoint( int initX, int initY );CPoint( POINT initPt );CPoint( SIZE initSize );第81页/共110页第八十二页,共111页。832运算符重载(zhn zi) 运算符重载本质上就是函数的重载,是函数重载的特殊形式(xngsh)(函数名为运算符号),VC语言中允许程序员重新定义运算符的语义,这一机制称为运算符重载。 与函数重载(zhn zi)类似,运算符重载(zhn zi)就是当运算符的操作对象不同时,运算符呈现出不同的运算状态。

36、运算符函数有两种形式:一种是在类中定义的运算符成员函数,即类成员运算符;另一种是在类之外定义的运算符函数,通常使用友元形式,即友元运算符 。第82页/共110页第八十三页,共111页。84类的运算符重载的定义形式类型(lixng) 类名:operator重载运算符(参数表)/运算符函数体【例3-22】用类的成员函数(hnsh)重载运算符“+”实现复数相加的例子,重载运算符“= =”实现两个复数是否相等的判断。程序的主文件为第83页/共110页第八十四页,共111页。85#include class TComplex /定义数学上的复数类public:TComplex(float real=0,

37、float image=0); /缺省构造函数(hnsh)TComplex(const TComplex &other); /拷贝构造函数(hnsh)TComplex operator +(const TComplex &other); /加法运算符重载bool operator =(const TComplex &other) /判断两个复数是否相等的内联函数(hnsh)实现return (m_real=other.m_real)&(m_image=); void ShowValue(); /显示复数值private:float m_real; /复数的实部

38、float m_image;/复数的虚部;第84页/共110页第八十五页,共111页。86TComplex:TComplex(float real,float image) /缺省的构造函数的实现m_real=real;m_image=image;TComplex:TComplex(const TComplex &other) /拷贝构造函数的实现m_real=;m_image=;TComplex TComplex:operator +(const TComplex &other) /加法(jif)运算符重载的实现代码TComplex temp;=;=;return temp;

39、第85页/共110页第八十六页,共111页。87void TComplex:ShowValue() /显示复数值代码 cout0)cout+m_imagei; if(m_image0)coutm_imagei; coutendl;void main()TComplex Complex1(6,8); /将复数Complex1设置为4+5iTComplex Complex2(-2,-3); /将复数Complex1设置为-2-3i,调用缺省构造函数完成(wn chng)TComplex Complex3(Complex1); /用Complex1初始化Complex3,调用拷贝构造函数完成(wn

40、chng)后,这两个复数相等TComplex Complex4,Complex5; /将复数Complex4,Complex5设置为0,调用缺省构造函数完成(wn chng)第86页/共110页第八十七页,共111页。88Complex1.ShowValue(); /显示复数complex1Complex2.ShowValue();Complex3.ShowValue();Complex4.ShowValue();Complex5.ShowValue();Complex4=Complex1+Complex2; /以运算符形式调用复数的相加,和两个数的普通加法形式一样Complex4.ShowV

41、alue();Complex5=Complex1.operator +(Complex2); /以函数形式调用复数的相加,注意在运算符的前面必须加上关键字operatorComplex5.ShowValue();if(Complex4=Complex5) /利用重载(zhn zi)的运算符=判断两个复数是否相等coutComplex4和Complex5相等n;elsecoutComplex4和Complex5不相等n;第87页/共110页第八十八页,共111页。89程序运行结果(ji gu):6+8i-2-3i6+8i004+5i4+5iComplex4和Complex5相等 运算符重载(zh

42、n zi)增加了程序的灵活性,但运算符重载(zhn zi)不能改变运算符的基本功能,也不能改变运算符的优先级和结合性,运算符重载(zhn zi)不能使用缺省参数。第88页/共110页第八十九页,共111页。901定义超载(overriding)函数要使程序出现运行时的多态性,必须有继承关系。在类的层次结构中,定义完全相同的函数原型,但这些类层次中同名(tngmng)函数的实现代码却不同。这些不仅同名(tngmng)而且同原型的函数称作函数的超载(override)。 2声明(shngmng)超载函数为虚函数 1、声明虚拟函数 class TAnimal private: char m_strN

43、ame10; public: virtual void Roar() cout并不知道哪个类的动物在叫endl;/此函数说明为虚函数 ; 2 、使用继承 第89页/共110页第九十页,共111页。913通过基类指针(zhzhn)来访问 一般情况下,指向一种类型对象的指针不允许(ynx)指向另一种类型的对象。但指向基类的指针可以指向派生类对象 【例3-23】虚函数和多态性的应用实例。 程序中定义了鸟类、狗类和老虎类,我们知道,不论是鸟、狗还是老虎,他们都会叫,但它们(t men)的叫声是完全不同的。如果这三个类都有一个叫Roar()的成员函数,那么在这三个类的Roar函数的实现代码肯定是不一样的

44、。在TAnimal类的Roar函数之前加上Virtual,使其成为虚函数,然后再通过指向基类TAnimal的指针来访问,就可实现运行时的多态性。程序的主文件为。第90页/共110页第九十一页,共111页。92#include #include #include class TAnimalprivate:char m_strName10;public:virtual void Roar() cout并不知道哪个(n ge)类的动物在叫endl;void SetName(char *strName)strcpy(m_strName,strName);char *GetName()return m_

45、strName; class TBird:public TAnimal /定义鸟类TBirdpublic:TBird() SetName(Bird);void Roar()coutTheGetName()is Roaringis it a good singer?n;第91页/共110页第九十二页,共111页。93class TDog:public TAnimal /定义(dngy)狗类TDogpublic:TDog() SetName(Dog);void Roar()coutThe GetName()is Roaringis it boring?n;class TTiger:public T

46、Animal /定义(dngy)老虎类TTigerpublic:TTiger() SetName(Tiger);void Roar()coutTheGetName()“is Roaringis it frightful?n;第92页/共110页第九十三页,共111页。94void main()TAnimal animal;TBird bird;TDog dog;TTiger tiger; cout以下为静态(jngti)联编-n;/通过对象的方式来访问是静态(jngti)联编();();();();coutRoar();pAnimal=&dog;pAnimal-Roar();pAnim

47、al=&tiger;pAnimal-Roar();第93页/共110页第九十四页,共111页。95 程序运行结果为: 以下为静态(jngti)联编- 并不知道哪个类的动物在叫 The Bird is Roaring.is it a good singer? The Dog is Roaring.is it boring? The Tiger is Roaring.is it frightful? 以下为动态联编- The Bird is Roaring.is it a good singer? The Dog is Roaring.is it boring? The Tiger is

48、Roaring.is it frightful?第94页/共110页第九十五页,共111页。96 通过指针的方式来访问虚函数是动态联编,倘若把派生类的Roar函数前的virtual去掉,则变为静态联编。自己(zj)把去掉virtual的程序运行一下,其运行结果为:以下为静态联编-并不知道哪个类的动物在叫The Bird is Roaring.is it a good singer?The Dog is Roaring.is it boring?The Tiger is Roaring.is it frightful?第95页/共110页第九十六页,共111页。97以下为动态联编-并不知道哪个类

49、的动物在叫并不知道哪个类的动物在叫并不知道哪个类的动物在叫 可见要实现动态联编,必须将基类的Roar定义成为虚函数,这种情形(qng xing)称为函数的超载(Override)或同名覆盖第96页/共110页第九十七页,共111页。98纯虚函数(hnsh)的定义 在基类中只声明虚函数而不给出具体的定义,将它的具体定义放在各派生类中,称此虚函数为纯虚函数(pure virtual function)。 声明了纯虚函数的类,称为抽象类(abstract class)。纯虚拟函数的声明形式如下(rxi):virtual 函数类型 函数原型(参数表)=0;将虚拟函数的原型设置为0,该虚函数即为纯虚函数

50、。第97页/共110页第九十八页,共111页。99(2)抽象类的定义(dngy) 只能用作别的类的基类,而本身不能直接创建对象的类称为抽象基类。带有纯虚函数的基类是抽象类。 抽象类派生(pishng)一个新类后,可以对虚函数添加实现代码,此时,该类就不再是抽象类;反之仍然为抽象类。(3)抽象类的使用(shyng) 【例3-24】纯虚函数的例子。下面的程序用于计算三角形和矩形的面积,设计一个抽象类shape,它表示具有形状的东西,体现了抽象的概念,在它下面可以派生出多种具体形状,比如三角形、矩形、椭圆等。为了计算这些图形的面积,只需在类shape中声明一纯虚函数area(),而将计算具体形状面积

51、的定义放到其派生类中。程序的主文件为。第98页/共110页第九十九页,共111页。100 #include class shape protected: double x, y;public: void set (double i, doube j)x=i; y=j; virtual void area()=0;/声明纯虚函数(hnsh);/抽象类shapt定义结束class triangle: public shape public: void area() cout ” Triangle S=1/2*” x”*” y”=”0.5*x*y”n”; / 派生类重新定义虚拟函数(hnsh);第9

52、9页/共110页第一百页,共111页。101class rectangle: public shape public: void area( ) cout ” Rectangle S=” x”*” y ”=”x*yset(5.1,10); p- area( ); p=&r; p-set(5.1,10); p-area();第100页/共110页第一百零一页,共111页。102程序(chngx)输出结果是: 基类shape 只为派生类提供一个接口(ji ku)area(),在派生类中给出area()的具体定义,因此将函数area()声明为纯虚函数。当shape的指针p指向派生类trian

53、gle的对象t时,语句p - area( )调用triangle类的函数area( ),显示三角形的面积。当p指向rectangle类的对象r时,相同语句p-area()调用的是rectangle类的函数area(),显示矩形的面积。 注意:从抽象类可以派生出具体或抽象类,但不能从具体类派生出一个抽象类。第101页/共110页第一百零二页,共111页。103(1)可以使程序简单易懂;(2)使程序模块间的独立性加强,增加了程序的易维护性;(3)提高了程序中“信息(xnx)隐藏”的等级;(4)提高了“软件重用”的等级。虚函数是一类簇对外提供的接口,它实质上是一种接口重用。 在程序(chngx)设计

54、中利用虚函数实现类的成员函数的动态联编,可以提高程序(chngx)的质量,采用虚函数对程序(chngx)的好处有:第102页/共110页第一百零三页,共111页。104一、单选题: 1下列说法(shuf)正确的是_ A. 内联函数在运行时是将给函数的目标代码插入每个调用该函数的地方 B. 内联函数在编译时是将给函数的目标代码插入每个调用该函数的地方 C. 类的内联函数必须在类体内定义 D. 类的内联函数必须在类体外通过关键字inline 定义 2为同一函数和运算符定义几个版本是VC语言的_ A. 抽象性 B. 继承性 C. 灵活性 D. 多态性第103页/共110页第一百零四页,共111页。105 3.下列关于封装的说法中正确的是_ A. 在VC中,封装是

温馨提示

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

评论

0/150

提交评论