《《C重点知识回顾》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《C重点知识回顾》PPT课件.ppt(47页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、MFC编程技术编程技术南京理工大学南京理工大学计算机学院计算机学院刘传才1 C+重点回顾重点回顾2一:概述较早的软件开发,用结构化程序设计方法。程序的定律是:程序程序=(算法算法)+(数据结构数据结构)在面向对象中,算法与数据结构被捆绑在面向对象中,算法与数据结构被捆绑成一个类,面向对象程序的基本元素是成一个类,面向对象程序的基本元素是对象。现实世界本身就是一个对象的世对象。现实世界本身就是一个对象的世界,任何对象都具有一定的属性与操作,界,任何对象都具有一定的属性与操作,也就总能用数据结构与算法两者合一地也就总能用数据结构与算法两者合一地来描述。来描述。3类的特性类的特性类在类在OOP中被表
2、示为由一组数据项和作中被表示为由一组数据项和作用在其上的一组操作所构成的整体。用在其上的一组操作所构成的整体。“学生类学生类”可由学号、姓名、学分等数据可由学号、姓名、学分等数据项和对这些数据的录入、修改和查询等项和对这些数据的录入、修改和查询等操作组成。类中的数据项一般称为实例操作组成。类中的数据项一般称为实例变量或数据成员,类中的操作一般称为变量或数据成员,类中的操作一般称为方法或成员函数。方法或成员函数。4类的定义和使用在在OOP中中,总总是是先先定定义义类类,再再由由类类生生成成其其对对象象。一一 个个 类类 所所 生生 成成 的的 对对 象象 称称 为为 该该 类类 的的 实实 例例
3、(instance)。一一个个类类的的所所有有对对象象都都是是由由类类生生成成的的,反反过过来来,类类的的所所有有对对象象都都共共享享类类中中的的所所有有数数据据项项和和操操作作方方法法。这这样样,在在逻逻辑辑上上每每一一个个对对象象都都包包含含数数据据和和操操作作两两部部分分,但但在在物物理理上上同同类类的的所所有有对对象象都都共共享享类类中中的的数数据据项项和和方方法法。因因此此,对对象象可可理理解解为:为:对象对象=(算法算法+数据结构数据结构)面向对象程序的结构特点是,程序一般由类的面向对象程序的结构特点是,程序一般由类的定义和类的使用两部分组成。程序中的一切操定义和类的使用两部分组成
4、。程序中的一切操作都是通过向对象发送相应的消息来实现的。作都是通过向对象发送相应的消息来实现的。对象接收到消息后,启动有关方法完成相应的对象接收到消息后,启动有关方法完成相应的操作。操作。5消息消息就是要求对象进行某种活动消息就是要求对象进行某种活动(操作操作)的信息。在面向对象程序中,要求某对的信息。在面向对象程序中,要求某对象作某操作时,就向该对象发送一个相象作某操作时,就向该对象发送一个相应的消息;当对象接收到发向它的消息应的消息;当对象接收到发向它的消息时,就调用有关的方法,执行相应的操时,就调用有关的方法,执行相应的操作。在面向对象程序中对象的一切活动,作。在面向对象程序中对象的一切
5、活动,只能通过消息去驱动。消息传递也是对只能通过消息去驱动。消息传递也是对象间进行通信的唯一方式。象间进行通信的唯一方式。6二 C+对C在过程语言方面的扩充 1作用域标识符作用域标识符“:”称称为为作作用用域域标标识识符符,它它用用来来解解决决局局部部变变量量与与全全局局变变量量的的重重名名问问题题。即即在在局局部部变变量量的的作作用用域域内内,可可用用“:”对被隐藏的同名全局变量进行访问。如对被隐藏的同名全局变量进行访问。如intx=1/全局变量全局变量intf2()floatx=1.2/局部变量局部变量 coutxl=x/输出局部变量输出局部变量x的值的值 coutx2=:x/输出全局变量
6、输出全局变量x的值的值172 函数原型 C+要要求求在在函函数数的的声声明明中中必必须须明明确确指指出出函函数数返返回回值值和和各各个个参参数数的的类类型型,这这一一形形式就称为函数的原型。例如式就称为函数的原型。例如int f4(int a,int b)就就是是函函数数f4的的原原型型。函函数原型的一般表示形式为数原型的一般表示形式为 (类类型型1,);在在程程序序中中,一一个个函函数数的的原原型型要要求求必必须须出出现在该函数的调用语句之前。现在该函数的调用语句之前。83 函数名重载 函函数数名名重重载载就就是是用用同同一一个个函函数数名名定定义义不不同同的的函函数数,即即同同一一个个函函
7、数数名名,但但函函数数的的返返回回类类型型、函函数数的的参参数类型或个数、函数体等却不同。例如数类型或个数、函数体等却不同。例如 int max(int i1,int i2);float max(float f1,float f2);double max(double d1,double d2);这三个函数的名都是这三个函数的名都是max,但它们又是不同的函,但它们又是不同的函数,这就是一种函数名重载。函数名重载在数,这就是一种函数名重载。函数名重载在C+中是允许的中是允许的(但在但在C语言中是不行的,在语言中是不行的,在C语言中语言中上述三个函数就必须采用不同的名字上述三个函数就必须采用不同
8、的名字)。当调用。当调用重载函数时,编译程序根据其所带参数的个数和重载函数时,编译程序根据其所带参数的个数和类型来进行选择类型来进行选择 94 缺省参数函数 缺缺省省参参数数有有双双重重含含义义:其其一一指指在在函函数数原原型型中中可可以以给给出出参参数数的的初初始始值值(称称为为缺缺省省值值或或默默认认值值);其其二二指指函函数数调调用用时时允允许许缺缺省省部部分分或或全全部部实实参参,缺缺省省的的这这些些实实参参,系系统统自自动动按按该该函函数数原原型型中中给给出出的的缺缺省省值值处处理。例如理。例如void fb(int a,int b=0,int c=1);/b的缺省的缺省值为值为0,
9、c的缺省值为的缺省值为1 10 5 内联函数内内联联函函数数也也称称内内置置函函数数,就就是是在在编编译译时时把把该该函函数数的的程程序序代代码码插插入入到到调调用用该该函函数数的的语语句句之之处处,以以便便在在程程序序运运行行时时不不再再进进行行函函数数调调用用。程程序序中中的的内内联联函函数数用用inline标标识识。设设置置内内联联函函数数的的目目的的是是为为了了消消除除函函数数调调用用时时的的系系统统开开销销,以以提提高高运运行行速速度度,但但这这是是一一种种用用空空间间换换时时间间的的措措施施,故仅适合一些小函数。故仅适合一些小函数。116 引用类型 引用作为一种变量类型用符号引用作
10、为一种变量类型用符号&表示。表示。例例如如,X&就就表表示示一一个个引引用用类类型型,X为为被被引引用用的的类类型型名名,则则 X&y(或或X&y,或或X&y)就就表表示示变变量量y为为一一引引用用类类型型,是是对对类类型型为为X的的某某变变量量的的引引用。用。引用类型的说明一般要立即进行初始化,如引用类型的说明一般要立即进行初始化,如 int i;int&ri=i;就就表表示示变变量量ri引引用用了了变变量量i,这这时时ri就就可可看看作作是是i的别名,即它们指向同一个内存单元。的别名,即它们指向同一个内存单元。12三 类与对象的定义 1 类的定义类的定义 C+中的类是由一组描述对象属中的类
11、是由一组描述对象属性或状态的数据项和作用在这些数性或状态的数据项和作用在这些数据项上的操作构成的封装体。其中据项上的操作构成的封装体。其中的数据称为数据成员,操作称为成的数据称为数据成员,操作称为成员函数。员函数。13类的代码定义C+中,类的定义格式一般如下:中,类的定义格式一般如下:class private:protected:public:;14类的定义复习类类的的定定义义由由关关键键字字class打打头头,后后跟跟类类名名,类类名名之之后后是是类类体体,它它被被括括在在花花括括号号中中,最最后后以以一一个个分号分号“;”结束。结束。类类体体中中一一般般有有三三个个关关键键字字:priv
12、ate、protected、public,称称为为访访问问权权限限关关键键字字。每每个个关关键键字字下下面又都可有数据成员和成员函数面又都可有数据成员和成员函数其其中中数数据据成成员员就就是是表表示示对对象象的的属属性性或或状状态态的的数数据据项项,当当然然在在这这里里它它们们都都是是变变量量,也也就就是是OOP中所称的实例变量中所称的实例变量(本应是属性变量本应是属性变量);成成员员函函数数则则是是作作用用于于数数据据成成员员的的操操作作,它它一一般般是是一一个个用用户户定定义义的的C+函函数数。成成员员函函数数也也就就是是OOP中中所所称称的的方方法法。数数据据成成员员和和成成员员函函数数
13、一一般般也统称为类的成员。也统称为类的成员。15几点说明需要说明的是:需要说明的是:(1)对对一一个个具具体体的的类类来来讲讲,上上述述定定义义式式中中的的三三个个部部分分并并非非一一定要全有,但至少要有其中的一个部分。定要全有,但至少要有其中的一个部分。(2)若若私私有有部部分分处处于于类类体体中中第第一一部部分分时时关关键键字字private可可以以省省略略。这这样样,如如果果一一个个类类的的体体中中没没有有一一个个访访问问权权限限关关键字,则其中的数据成员和成员函数都默认为私有的。键字,则其中的数据成员和成员函数都默认为私有的。(3)private、protected、public的的次
14、次序序和和出出现现的的次次数数可可以以星星任任意意的的。这这也也就就是是说说,一一个个类类的的定定义义中中也也可可以以有有多多于于一个的私有部分、保护部分或共有部分。一个的私有部分、保护部分或共有部分。下面以学生类为例,介绍类的定义方法。学生是个抽下面以学生类为例,介绍类的定义方法。学生是个抽象概念,其内涵至少应包含学号、姓名、性别、年龄、象概念,其内涵至少应包含学号、姓名、性别、年龄、学习成绩等属性,这些属性都可用数据项来表示。学生学习成绩等属性,这些属性都可用数据项来表示。学生属性数据项上的操作有置初值、修改、查询等。这些数属性数据项上的操作有置初值、修改、查询等。这些数据和操作可以构成一
15、个类,即学生类。下面给出了学生据和操作可以构成一个类,即学生类。下面给出了学生类的定义。为简单起见,先只取学号和成绩两个数据项。类的定义。为简单起见,先只取学号和成绩两个数据项。16一个例子例例4 定义学生类定义学生类clsss Student private:int number;/学号学号 float score;/成绩成绩 public:void input(int number1,float scorel)/数据录入数据录入 number=numberl;score=scorel;void modify(float scorel)/数据修改数据修改 score=scorel;void
16、print()/数据输出数据输出 coutn number:numberscore:score;学学生生类类的的名名字字为为Student,类类中中有有两两个个私私有有数数据据成成员员:number和和score,三个公有的成员函数:三个公有的成员函数:input、modify和和print。172 对象的生成在在C+中中,一一个个类类也也就就是是用用户户定定义义的的一一个个数数据据类类型型,而而且且是是一一个个抽抽象象数数据据类类型型。所所以以,类类定定义义好好以以后后,就就可可以以声声明明类类的的变变量量,然然后后对对类类变变量量进进行行赋赋值值和和其其他他各各种操作。种操作。一一个个含含
17、值值的的类类变变量量就就是是所所属属类类的的一一个个对对象象,亦亦称称为为类类实实例例。例例如如下下面面的的语语句句就就声声明明了了一一个个Student类类的的变变量量,并并且且用用成成员员函函数数input对对其其赋赋初初值值,于于是是就就得得到到了了一一个个Student类的对象类的对象(即实例即实例)a。Studenta;/变量声明变量声明a.input(10,90);/变量初始化变量初始化对对象象a描描述述了了现现实实世世界界中中的的一一个个学学号号为为10,学学习习成成绩绩为为90的学生。的学生。由类得到对象,一般称由类生成对象或创建对象。由类得到对象,一般称由类生成对象或创建对象
18、。183 构造函数和析构函数(1)构造函数构造函数构构造造函函数数的的特特点点是是函函数数名名同同其其类类名名相相同同,但但无无任任何何返返回类型。例如,我们可给回类型。例如,我们可给Student类定义构造函数如下:类定义构造函数如下:Student:Student(int numberl,float scorel)nutuber=numberl;score=scorel;有有了了这这个个构构造造函函数数,在在声声明明一一个个类类变变量量时时,系系统统就就自自动动调调用用构构造造函函数数对对变变量量进进行行初初始始化化,而而生生成成对对象象。例例如下面的语句就同样创建了对象如下面的语句就同样
19、创建了对象a。Student a(10,90);19生成对象的语法利用构造函数直接创建对象的利用构造函数直接创建对象的一般语法一般语法形式为:形式为:(;利利用用构构造造函函数数创创建建对对象象的的第第二二种种方方法法是是,用用指指针针和算符和算符new实现实现。其一般语法形式为:其一般语法形式为:*=new();例如,例如,Student*pa=newStudent(10,90);就创建了对象就创建了对象(*pa)。20(3)析构函数由由于于增增加加的的数数据据成成员员是是字字符符指指针针,所所以以,构构造造函函数数中中使使用用操操作作符符new为为其其开开辟辟内内存存空空间间。这这样样的的
20、内内存存空空间间的的释释放放只只有有用用操操作作符符delete能能够够实实现现,但但如如果果每每次次都都要要在在程程序序中中显显式式地地写写出出删删除语句,则给编程带来了许多麻烦。除语句,则给编程带来了许多麻烦。C+采采用用了了析析构构函函数数的的办办法法来来解解决决这这一一问问题题。具具体体讲讲,就就是是针针对对一一个个类类的的构构造造函函数数,把把所所有有删删除除语语句句都都事事先先集集中中编编写写在在一一个个函函数数中中,在在程程序序运运行行过过程程中中,当当某某一一个个对对象象运运行行结结束束(即即超超出出了了作作用用域域)时时,系系统统就就自自动动调调用用这这个个函函数数,释释放放
21、由由new开开辟辟的的内内存存空空间间。这这就就实实现现了了内内存存空空间间的的自自动动释释放放。完完成成这这一一任任务务的的函函数数就就叫叫析析构函数。构函数。21(3)析构函数同同构构造造函函数数一一样样,析析构构函函数数与与所所属属类类同同名名,定定义义时时也也不不能能指指定定任任何何返返回回类类型型,但但析析构构函函数数的的函函数数名名前前要要有有一一个个“”号号,函函数数名名后后有有一一对对圆圆括括号号,且且其其中中无无参参数数,函数体内一般仅由函数体内一般仅由deletep;形形式式的的删删除除语语句句组组成成,其其中中p为为构构造造函函数数中中指指向向由由new所所开开辟辟的的内
22、内存存空空间间的的指指针针。225 友员 类类的的封封装装性性和和数数据据隐隐蔽蔽特特性性对对提提高高软软件件的的可可靠靠性性、可可重重用用性性和和可可维维护护性性起起到到了了重重要要作作用用,但但却却潜潜伏伏着着增增加加运运行行开开销销的的危危险险。因因为为每每次次通通过过成成员员函函数数访访问问类类的的隐隐蔽蔽数数据据时时,都都需需要要调调用用开开销销(对对非非内内联联函函数数),如如果果访访问问非非常常频频繁繁,调调用用开开销销就就很很大大,从从而而导导致致程程序序的的运运行行效率降低。效率降低。为为了了合合理理地地解解决决这这一一问问题题,C+提提供供了了友友员员这这一一语语言言设设施
23、施。所所谓谓友友员员,就就是是那那些些允允许许访访问问类类中中私私有有数数据据和和保保护护数数据据的的非非本本类类的的函函数数。换换句句话话说说,作作为为一一个个类类的的友友员员的的类类外外函函数数,可可以以象象本本类类的的成成员员函函数数一一样样自自由由地访问类中的任何成员。地访问类中的任何成员。一一个个类类的的友友员员需需要要在在类类的的定定义义中中声声明明。声声明明可可以以出出现现在在类类的的私私有有、保保护护或或共共公公有有部部分分,其其作作用用都都一一样样。友员声明的语法形式为友员声明的语法形式为friend23例子例如例如 void f1(int x,float y).class
24、X friend void f1(int x,float y);友员同一般成员函数的区别是,友员函数没友员同一般成员函数的区别是,友员函数没有有this指针。指针。24三 消息传递 由类的概念可知,要改变对象的属性或由类的概念可知,要改变对象的属性或状态,只能靠向对象发送消息来实现。状态,只能靠向对象发送消息来实现。用面向对象程序设计的话来说就是,对用面向对象程序设计的话来说就是,对于一个对象中的数据的操作,只能通过于一个对象中的数据的操作,只能通过向对象发送消息,然后由对象自己调用向对象发送消息,然后由对象自己调用相应的方法去实现。在相应的方法去实现。在C+中,向对象中,向对象发送消息,是用
25、对象去调用相应的成员发送消息,是用对象去调用相应的成员函数的方式实现的。函数的方式实现的。25成员函数调用的语法成员函数调用的语法形式为成员函数调用的语法形式为 .其其中中对对象象是是消消息息的的接接收收者者,成成员员函函数数就就是要求对象所做的工作。例如是要求对象所做的工作。例如 Student a(10,LiMing,80);/取取上上节节中定义的中定义的Student类类 a.modify(85);a.print();26说明上上面面程程序序段段中中的的第第二二和和第第三三句句就就是是向向对对象象a发发送送的的两两条条消消息息。第第一一条条消消息息的的意意思思是是要要求求对对象象a修修改
26、改成成绩绩,即即调调用用方方法法modify将将自自己己的的成成绩绩改改为为85;第第二二条条消消息息是是要要求求对对象象a将将自自己己的的档档案案显显示示在在屏屏幕幕上。所以,这三个语句的执行结果就是上。所以,这三个语句的执行结果就是 number:10 name:LiMing score:85 27用指针创建的对象的情况对对于于用用指指针针创创建建的的对对象象,可可以以用用如如下下两两种种方方式式给给其其发发送消息:送消息:(1)(*p).(2)p-其其中中,p为为指指向向对对象象的的指指针针。下下面面程程序序段段中中就就采采用用了了这这两两种种发发送送消消息息的的方方式式,其其效效果果与
27、与上上一一个个程程序序段段是是一一样样的。的。Student*p=new student(10,LiMing,80);(*p).mdify(85);p-print();表达式表达式.就是就是C+的消的消息发送模式。这种消息模式也就是类中公有成员函数息发送模式。这种消息模式也就是类中公有成员函数的调用模式。的调用模式。28四 this指针 在类的成员函数中,对数据成员的操作是通用在类的成员函数中,对数据成员的操作是通用的,但在消息表达式中的函数调用却是有针对的,但在消息表达式中的函数调用却是有针对性的,它是指对特定对象的数据成员的操作。性的,它是指对特定对象的数据成员的操作。那么,当程序中调用一
28、个成员函数时,该成员那么,当程序中调用一个成员函数时,该成员函数是如何确定所操作的具体数据的呢函数是如何确定所操作的具体数据的呢?诚然,诚然,消息表达式的最前面有对象的名字,但内部是消息表达式的最前面有对象的名字,但内部是怎样实现的呢怎样实现的呢?C+在成员函数中事先设置了一个名为在成员函数中事先设置了一个名为this的指的指针,这个指针总是指向当前对象。针,这个指针总是指向当前对象。29五 派生类与继承 在在C+中,一个类往往还可以再划分为一些子中,一个类往往还可以再划分为一些子类。反过来看,一些具有共性的类也可以再进类。反过来看,一些具有共性的类也可以再进一步抽象而得到更高一层的类。一步抽
29、象而得到更高一层的类。一般来讲,子类除了继承父类的属性外,一定一般来讲,子类除了继承父类的属性外,一定还有自己独有的特殊属性。子类与父类之间的还有自己独有的特殊属性。子类与父类之间的这种关系,用这种关系,用C+的语言来讲就是,凡父类的的语言来讲就是,凡父类的成员也一定是子类的成员。而子类除了拥有父成员也一定是子类的成员。而子类除了拥有父类的成员外,还有自己独有的特殊成员。类的成员外,还有自己独有的特殊成员。C+中提供了类的表示和使用规则,也提供了中提供了类的表示和使用规则,也提供了子类的表示和使用规则,其中就隐含着子类对子类的表示和使用规则,其中就隐含着子类对父类的继承机制。父类的继承机制。C
30、+中中把把父父类类也也称称为为基基类类(Base Class),把把子子类也称为派生类类也称为派生类(Derived Class)或导出类。或导出类。301 派生类的定义 派生类的定义格式如下:派生类的定义格式如下:class :;其其中中符符号号“|”表表示示或或者者关关系系,花花括括号号中中是是派派生生类类的的界界面面声声明。明。例例如如,大大学学生生可可以以构构成成一一个个类类,即即大大学学生生类类。但但大大学学生生类类可可以以作作为为学学生生类类的的派派生生类类。下下面面就就是是利利用用学学生生类类定定义义的的大大学生类。学生类。class Ustudent:public Studen
31、t /Ustudent为大学生类类名为大学生类类名 char major;/专业专业 public:UStuden(int number1,char*name1,char*major,float score1);void print();312 派生类对其基类的继承派生类对其基类的继承(1)派派生生类类成成员员函函数数对对基基类类成成员员的的访访问问权权限限派生类中的成员函数只能够访问基类中派生类中的成员函数只能够访问基类中的的protected和和public成员。即能够直接成员。即能够直接操作操作protected和和public数据成员,也能数据成员,也能直接调用直接调用protecte
32、d和和public成员函数;成员函数;但派生类的成员函数不能访问基类的任但派生类的成员函数不能访问基类的任何何private成员。成员。32(2)基类成员作为派生类成员的成员性质 基基类类中中的的private成成员员对对派派生生类类是是不不可可访访问问成成员员;而而protected和和public成成员员对对派派生生类类可可以以仍仍然然是是protected和和public成成员员,也也可可以以全全部部为为private成成员员,取取决决于于派派生生类类定义式定义式 class:中的中的部分是选部分是选public还是还是private如如果果选选public,则则基基类类中中的的prot
33、ected和和public成成员员仍仍然然是派生类的是派生类的protected和和public成员;成员;如如果果选选private,则则基基类类中中的的protected和和public成成员员全全部部为派生类的为派生类的private成员。成员。如如果果这这一一项项缺缺省省,则则默默认认为为是是选选private。选选public的的派派生生类类也也称称为为公公有有派派生生类类,选选private的的派派生生类类也也称称为为私私有派生类。有派生类。33表1 派生类对基类成员的继承关系基类成员基类成员作作 为为 派派 生生 类类 成成 员员公有派生公有派生私有派生私有派生private成员
34、成员不可直接访问成员不可直接访问成员不可直接访问成员不可直接访问成员protected成员成员protected成员成员private成员成员public成员成员public成员成员private成员成员 34(3)派生类的构造函数和析构函数 派派生生类类也也要要有有构构造造函函数数,其其构构造造函函数数的的格格式式一般为:一般为::():()例如,大学生类的构造函数可实现如下:例如,大学生类的构造函数可实现如下:Ustudent:UStudent(int number1,char*name1,char*major1,float score1):Student(number1,name1,sc
35、ore1)35调用原理派派生生类类的的构构造造函函数数实实际际隐隐含含着着对对基基类构造函数的调用。类构造函数的调用。同基类一样,如果需要的话则派同基类一样,如果需要的话则派生类也要有析构函数。派生类的析生类也要有析构函数。派生类的析构函数中也应该调用基类的析构函构函数中也应该调用基类的析构函数数(如果基类有析构函数的话如果基类有析构函数的话)。36六 多态与虚函数 多态多态(polymorphism),通俗地讲,就是同一种,通俗地讲,就是同一种东西有多种形态。在程序语言中,所谓多态,东西有多种形态。在程序语言中,所谓多态,就是一个名字就是一个名字(符号串符号串)代表多个或多种具体的代表多个或
36、多种具体的对象。对象。例如,一个变量名代表多种类型的变量或指针,例如,一个变量名代表多种类型的变量或指针,一个符号代表多个语义不同的算符,一个函数一个符号代表多个语义不同的算符,一个函数名名(过程名过程名)代表多个参数类型不同的函数代表多个参数类型不同的函数(或或过程过程),一个类名代表成员类型不同的类等。,一个类名代表成员类型不同的类等。37联编编译时的多态是通过静态联编来实现的。编译时的多态是通过静态联编来实现的。所谓联编所谓联编(binding。亦称束定。亦称束定),就是把,就是把函数名与其函数体的程序代码连接函数名与其函数体的程序代码连接(联系联系)在一起。在一起。静态联编时,系统用实
37、参与形参进行匹静态联编时,系统用实参与形参进行匹配,对于同名的重载函数便根据参数上配,对于同名的重载函数便根据参数上的差异进行区分,然后进行联编。从而的差异进行区分,然后进行联编。从而实现了多态性。实现了多态性。38联编运行时的多态是用动态联编实现的。动运行时的多态是用动态联编实现的。动态联编态联编(也称晚联编也称晚联编)是程序运行时才进是程序运行时才进行的联编。即当程序调用到某一函数行的联编。即当程序调用到某一函数(过过程程)名时,才去寻找和连接其程序代码,名时,才去寻找和连接其程序代码,对面向对象程序而言,就是当对象接收对面向对象程序而言,就是当对象接收到某一消息时,才去寻找和连接相应的到
38、某一消息时,才去寻找和连接相应的方法。方法。392 虚函数的引入 我们先看下面的程序:我们先看下面的程序:class A;classB:public A;main()A a,*p;B b;p=&a;p=&b;/正确正确 这这个个程程序序说说明明了了这这样样的的事事实实:指指向向基基类类对对象象的的指指针针,也也可可以以指指向向它它的的公公有有派派生生类类的的对对象象。然然而而,当当用用这这种种对对象象指指针针调调用用同同名名但但不不同同级级的的成成员员函函数数时时,却却遇遇到到了了麻烦。请看下面的程序:麻烦。请看下面的程序:40例子voidA:print()coutA;voidB:print(
39、)coutprint();p=&b;p-ptint();return0;这个程序的运行结果是:这个程序的运行结果是:AA,而不是预想的:,而不是预想的:AB。41分析这个错误是由这个错误是由C+的静态联编机制造成的静态联编机制造成的。对于上面的程序,静态联编机制首的。对于上面的程序,静态联编机制首先将指向基类对象的指针先将指向基类对象的指针p与基类的成员与基类的成员函数函数print()连接在一起,这样,不管指针连接在一起,这样,不管指针p再指向哪个对象,再指向哪个对象,p-print()调用的总是调用的总是基类中的成员函数基类中的成员函数print()。为了解决这一。为了解决这一问题,问题,
40、C+引入了虚函数的概念。引入了虚函数的概念。42虚函数的定义3虚函数的定义虚函数的定义虚虚函函数数首首先先是是基基类类中中的的成成员员函函数数,这这个个成成员员函函数数在在派派生生类类中中被被重重载载,在在给给这这个个成成员员函函数数前前面面添添上上关关键键字字virtual后后,它它就就变变为为虚虚函函数数了了。例例如如,要要把把上上面面类类A中中print函数作为虚函数,即函数作为虚函数,即classApublic:virtualvoidprint();现在再运行上面的程序,结果就变为现在再运行上面的程序,结果就变为AB了了434 虚函数与重载函数的关系 在在一一个个派派生生类类中中重重载
41、载基基类类的的虚虚函函数数是是函函数数重重载载的的另另一一种种特特殊殊形形式式。这这种种重重载载不不同同于于一一般般的的函函数数重重载载。一一般般的的函函数数重重载载时时,函函数数的的返返回回类类型型及所带的参量可以不同,只要函数名相同即可。及所带的参量可以不同,只要函数名相同即可。当重载一个虚函数时,也就是说在派生类中重当重载一个虚函数时,也就是说在派生类中重新定义此虚函数时,要求函数名、返回类型、新定义此虚函数时,要求函数名、返回类型、参量个数、参量类型和顺序都与基类中的原型参量个数、参量类型和顺序都与基类中的原型完全相同,不能有任何的不同。若出现不同,完全相同,不能有任何的不同。若出现不
42、同,系统会根据不同情况分别处理。系统会根据不同情况分别处理。445 运算符重载 C+把把运运算算符符当当作作特特殊殊的的运运算算函函数数,我我们们可可以以像像使使用用预预定定义义运运算算符符一一样样使使用用自自定定义义运运算算符符和和友友元元运运算算符符。因因此此,可可以以创创建建自自定定义义运运算算符符来来支支持持自自定定义义类类,例例如如复复数数、字字符符串串、数数组组和和矩矩阵阵的的运运算算。这这些些自自定定义义运运算算符符可可用用来来书书写写可可读读性较好的表达式。性较好的表达式。运算符重载使程序员可把运算符重载使程序员可把C+运算符的定义扩运算符的定义扩展到运算分量是对象的情况。运算
43、符重载的目展到运算分量是对象的情况。运算符重载的目的是:使的是:使C+代码更直观,更易读。由简单的代码更直观,更易读。由简单的运算符构成的表达式常常比函数调用更简洁、运算符构成的表达式常常比函数调用更简洁、易懂。易懂。45定义方法运运算算符符在在一一个个类类中中重重载载(即即重重载载为为局局部部的的),则则仅仅在在该该类类中中有有效效。但但有有些些运运算算符符(如如new、delete)也也可可以以重重载载为为全全局局的的。如如果果重重载载为为全全局局的,则覆盖了语言中该运算符原有的定义。的,则覆盖了语言中该运算符原有的定义。运运算算符符重重载载的的方方法法有有两两种种:用用成成员员函函数数重重载载和和用用友友员员函函数数重重载载。用用成成员员函函数数重重载载运运算算符符的的一一般格式为般格式为 operator ()其其中中,operator是是函函数数的的关关键键字字。若若运运算算符符为为一一元元运运算算符符则则参参数数表表为为空空;若若为为二二元元运运算算符符,则则参参数数表表中中只只有有一一个个操操作作对对象象,这这个个操操作作对对象象代代表表右右操操作作数数,左左操操作作数数则则由由this指指针针传传给给该该函数。函数。46定义方法这种重载运算符函数的语义可表示为这种重载运算符函数的语义可表示为 .operator ()或或 .operator ()47
限制150内