《第4章 C++的面向对象编程.ppt》由会员分享,可在线阅读,更多相关《第4章 C++的面向对象编程.ppt(34页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第第4 4章章 C+C+的面向的面向对象象编程程C+是面向是面向对象的程序象的程序设计语言,言,类是其是其实现面向面向对象的工象的工具。具。类是面向是面向对象程序象程序设计(OOP)实现信息封装的基信息封装的基础,是是C+语言最重要的特性。言最重要的特性。类是是进行数据封装和数据保行数据封装和数据保护的工具。本章主要知的工具。本章主要知识点点为:类和和对象的基本概念;象的基本概念;友元;友元;派生派生类;继承与多重承与多重继承;承;多多态;函数重函数重载和运算符重和运算符重载;虚函数。虚函数。4.14.1类和和对象的基本概念象的基本概念类是是现实事物共有特征的抽象,而事物共有特征的抽象,而对象
2、是象是类的具体的具体实例。在例。在面向面向对象的程序象的程序设计中,中,总是先声明是先声明类,再由,再由类生成其生成其对象。象。类是建立是建立对象的模板,象的模板,对象象则是是类的一个的一个实例。例。4.1.14.1.1从从结构到构到类在在C语言中有一种自定言中有一种自定义的数据的数据类型:型:结构体。构体。结构体中可以函数构体中可以函数不同的数据不同的数据类型。型。C+语言把言把结构体构体进行行扩充,它不充,它不仅可以含可以含有不同的数据有不同的数据类型,而且可以含有函数。在型,而且可以含有函数。在C+中中结构体的定构体的定义形式如下:形式如下:struct 结构体名构体名成成员表列表列变量
3、名表列量名表列;struct是定是定义结构体的关构体的关键字,后面的字,后面的结构体名是构体名是结构体的名称。构体的名称。在在结构体中可以定构体中可以定义一个或多个成一个或多个成员变量或量或这函数。当然也可函数。当然也可以不定以不定义变量,此量,此时称称为空空结构体。构体。变量名表列是在定量名表列是在定义结构构体体时,同,同时定定义结构体构体变量。也可以不定量。也可以不定义变量,在后面用到量,在后面用到的地方在定的地方在定义结构体构体变量。需要注意的是量。需要注意的是结构体右括号的构体右括号的变量量名表列后面需要添加一个名表列后面需要添加一个“;”。4.1.24.1.2成成员函数的定函数的定义
4、类中含有两种成分:数据成中含有两种成分:数据成员和函数成和函数成员。函数成。函数成员又称又称为成成员函数。成函数。成员函数的定函数的定义有两种方式。有两种方式。1方式一方式一2方式二方式二4.1.34.1.3对象的定象的定义与使用与使用对象是象是类的具体的具体实例,定例,定义好好类以后必以后必须去定去定义类的的对象才象才可以真正的去可以真正的去实现类的功能。一般情况下的功能。一般情况下对象的定象的定义有下有下面两种情况。面两种情况。1声明声明类时直接定直接定义对象象2声明声明类之后再定之后再定义对象象4.1.44.1.4对象的作用域象的作用域类是面向是面向对象的体象的体现,它具有一定的数据保,
5、它具有一定的数据保护功能。功能。类的作的作用域就是用域就是类的保的保护功能的机制。功能的机制。类的作用域是指的作用域是指类的声明的声明部分中的一部分中的一对花括号所形成的作用域。一个花括号所形成的作用域。一个类的所有成的所有成员都在都在该类的作用域内。在上面的例子中已的作用域内。在上面的例子中已经看到看到类的私有的私有成成员变量不可以在量不可以在类的外部所的外部所访问,因此需要定,因此需要定义一个公一个公有成有成员函数函数间接的接的访问类的私有成的私有成员。4.24.2构造函数和析构函数构造函数和析构函数类是一种用是一种用户自定自定义的数据的数据类型。定型。定义一个一个类的的对象象时,编译程序
6、需要程序需要为对象分配存象分配存储空空间,进行必要的初始化工作。行必要的初始化工作。在在C+中中类的构造函数就是去的构造函数就是去实现这部分功能。部分功能。4.2.14.2.1构造函数构造函数构造函数是一种特殊的成构造函数是一种特殊的成员函数,它主要函数,它主要进行一些初始化工行一些初始化工作。构造函数有一些基本性作。构造函数有一些基本性质:(1)构造函数和)构造函数和类的名字相同。的名字相同。(2)构造函数不具有返回)构造函数不具有返回值。(3)定)定义对象象时,系,系统自自动调用构造函数。用构造函数。(4)构造函数是公有函数,但它不可以被)构造函数是公有函数,但它不可以被显示示调用。用。4
7、.2.24.2.2默默认参数的构造函数参数的构造函数对于有参数的构造函数,在定于有参数的构造函数,在定义对象象时必必须给构造函数构造函数传递参数。参数。实际情况中,情况中,虽然有些构造函数有参数,但其参数然有些构造函数有参数,但其参数是不是不变的,的,这就是默就是默认参数的构造函数。此参数的构造函数。此时构造函数的构造函数的形式如下:形式如下:类名名(函数名函数名)(参数参数1=默默认值,参数,参数2=默默认值,.)构造函数中的参数与普通函数的参数是一构造函数中的参数与普通函数的参数是一样的,所的,所谓的默的默认参数即参数即为该参数参数设置一个默置一个默认的取的取值。可以。可以为全部或者部全部
8、或者部分参数分参数设置默置默认值。4.2.34.2.3析构函数析构函数析构函数也是一种特殊的成析构函数也是一种特殊的成员函数,它函数,它执行和构造函数相反行和构造函数相反的工作。析构的特殊性的工作。析构的特殊性质如下:如下:(1)析构函数名称与)析构函数名称与类名相同,但前面加一个名相同,但前面加一个“”。(2)一个)一个类中只有一个析构函数,并且中只有一个析构函数,并且该函数不函数不带任何参任何参数。数。(3)当撤)当撤销对象象时编译系系统自自动调用析构函数。用析构函数。(4)若程序)若程序员没有定没有定义析构函数,析构函数,编译系系统会生成析构函会生成析构函数。数。4.2.44.2.4重重
9、载构造函数与拷构造函数与拷贝构造函数构造函数C+允允许重重载构造函数,所构造函数,所谓的重的重载构造函数是指允构造函数是指允许在在类中有多个构造函数。当然中有多个构造函数。当然这些构造函数肯定是有区些构造函数肯定是有区别的。的。各个构造函数必各个构造函数必须拥有不同的参数个数或者参数有不同的参数个数或者参数类型。型。4.34.3友元友元类的主要特点是是数据的主要特点是是数据隐藏,即藏,即类的私有成的私有成员只可以被只可以被类的的内部使用,但是有的内部使用,但是有的时候需要在候需要在类的外部的外部访问类的私有成的私有成员,为此此C+利用了一种新的机制利用了一种新的机制友元。友元。4.3.14.3
10、.1友元函数友元函数友元函数不是友元函数不是类的成的成员函数,而是独立于当前函数,而是独立于当前类的外部函数,的外部函数,但它可以但它可以访问该类的所有成的所有成员。在。在类的定的定义中声明友元函中声明友元函数数时,需要在函数名前面加上,需要在函数名前面加上friend。友元函数可以定。友元函数可以定义在在类的内部,也可以在的内部,也可以在类的外部定的外部定义。注意:友元在注意:友元在类的封装性中打了个孔,使封装性的的封装性中打了个孔,使封装性的强度下降,度下降,程序中如非必要,程序中如非必要,应尽量减少友元的使用。尽量减少友元的使用。4.3.24.3.2友元成友元成员除了一般的函数可以作除了
11、一般的函数可以作为类的友元外,一个的友元外,一个类的成的成员函数也函数也可以作可以作为另一个另一个类的友元。的友元。这样的函数不的函数不仅可以可以访问本本类的所有成的所有成员,还可以可以访问其友元其友元类的所有成的所有成员。需要注意。需要注意的是当在一个的是当在一个类中的某个成中的某个成员函数定函数定义为另一个另一个类的友元的友元函数函数时需要首先定需要首先定义此此类。例如要定。例如要定义类A的某个函数的某个函数为类B的友元函数,那么需要先定的友元函数,那么需要先定义类B,然后再,然后再进行行类A的的成成员函数与函数与B友元的定友元的定义。4.3.34.3.3友元友元类不不仅函数可以作函数可以
12、作为一个一个类的友元,一个的友元,一个类也可以作也可以作为另一个另一个类的友元。定的友元。定义方法是在方法是在类的声明中加入的声明中加入语句句friend类名。名。4.44.4派生派生类继承是面向承是面向对象程序象程序设计的一个重要特性,它允的一个重要特性,它允许在在现有有类的基的基础上上创建新的建新的类,可以,可以继承原有承原有类数据和函数,同数据和函数,同时可以添加新的成可以添加新的成员。继承特性增加了代承特性增加了代码的重复利用率,的重复利用率,加快开加快开发效率。通效率。通过继承已有的一个或多个承已有的一个或多个类产生一个新生一个新类的的过程称程称为派生。通派生。通过派生可以派生可以创
13、建一种新的建一种新的类,所,所创建的新建的新类称称为派生派生类。4.4.14.4.1派生派生类的引出的引出现实世界中,世界中,继承的概念十分广泛。人承的概念十分广泛。人们认识世界就是一个世界就是一个层次次结构。越靠近上构。越靠近上层就表示越就表示越为普遍的概念,例如下面普遍的概念,例如下面的一个的一个层次次结构:构:在在类中,中,继承的概念就是从父承的概念就是从父辈得到其属性。即得到其属性。即产生的新生的新类就是原有就是原有类的派生。原有的派生。原有类就是派生就是派生类的基的基类。派生。派生类的的声明形式如下:声明形式如下:class 类名:名:继承方式承方式 基基类4.4.24.4.2基基类
14、成成员在派生在派生类中中访问属性属性派生派生类继承基承基类的方式有三种情况,那么的方式有三种情况,那么继承承过来的成来的成员其其属性如何呢?下面属性如何呢?下面给出三种出三种继承方式下的基承方式下的基类成成员在派生在派生类中的中的访问属性。属性。4 4.4.3.4.3派生派生类对基基类成成员的的访问规则派生派生类对基基类成成员的的访问形式包括内部形式包括内部访问和和对象象访问两种两种方式。下面方式。下面对三种三种继承方式下的承方式下的访问规则分分别进行介行介绍。1私有私有继承承2保保护继承承3公有公有继承承4.54.5派生派生类的构造函数与析构函数的构造函数与析构函数派生派生类继承了基承了基类
15、的成的成员,实现了代了代码的重复利用,但是的重复利用,但是继承的目的更主要的是功能的承的目的更主要的是功能的扩充。基充。基类的构造函数和析构的构造函数和析构函数不能被函数不能被继承。如果在派生承。如果在派生类中需要中需要对新增加的成新增加的成员进行初始化,行初始化,则需要加入派生需要加入派生类的构造函数。同的构造函数。同样派生派生类也也需要添加虚构函数来需要添加虚构函数来实现一些一些结束工作。束工作。4.5.14.5.1派生派生类构造函数和析构函数的构造函数和析构函数的执行行顺序序当当创建建对象象时,编译系系统会自会自动调用构造函数。当撤用构造函数。当撤销对象象时,编译系系统会自会自动调用析构
16、函数。当用析构函数。当创建派生建派生类的的对象象时,首先,首先执行基行基类的构造函数,然后的构造函数,然后执行派生行派生类的构造函的构造函数。当撤数。当撤销对象象时,则先先执行派生行派生类的析构函数,然后再的析构函数,然后再执行基行基类的析构函数。的析构函数。4.5.24.5.2派生派生类构造函数和析构函数的构造构造函数和析构函数的构造规则派生派生类不能不能继承基承基类的构造函数,如果基的构造函数,如果基类中含有中含有带参数的参数的构造函数,构造函数,则派生派生类中必中必须定定义构造函数,用以向基构造函数,用以向基类传递参数。派生参数。派生类的构造函数的定的构造函数的定义必必须包含基包含基类的
17、参数,的参数,其定其定义的一半格式的一半格式为:派生派生类名(全部参数列表):基名(全部参数列表):基类名(参数列表)名(参数列表)派生派生类的析构函数和基的析构函数和基类的析构函数关系不大,程序中可以的析构函数关系不大,程序中可以分分别进行行设计。4.64.6继承与多重承与多重继承承继承使得派生承使得派生类既保持了基既保持了基类的特性,又可以增加新的功能。的特性,又可以增加新的功能。如果一个如果一个类,其属性可以从多个基,其属性可以从多个基类中中获得,得,这就需要多就需要多重重继承的概念。承的概念。4.6.14.6.1继承和多重承和多重继承承继承是一个承是一个类从一个基从一个基类中派生,多重
18、中派生,多重继承承则是指一个是指一个类从从多个基多个基类进行派生。行派生。现在有一个在有一个类A和和类B,现在要在要设计一个一个类C,它需要既,它需要既继承承类A的特性,又的特性,又继承承类B的特性,的特性,那么那么类C就需要多成就需要多成继承承类A和和类B。4.6.24.6.2多重多重继承的声明承的声明在在C+中,中,类的多重的多重继承与承与单继承的声明相似,其一般形式承的声明相似,其一般形式是:是:class 派生派生类名:名:继承方式承方式1 基基类1,继承方式承方式n 基基类n 在多重在多重继承中,派生承中,派生类的构造函数要的构造函数要进行基行基类的初始化工作,的初始化工作,因此如果
19、任何一个基因此如果任何一个基类的构造函数含有参数,那么派生的构造函数含有参数,那么派生类必必须添加构造函数。构造函数的添加构造函数。构造函数的执行行顺序是先序是先执行基行基类的的构造函数。在构造函数。在执行派生行派生类的构造函数,同一的构造函数,同一层次的基次的基类的的执行行顺序与声明序与声明时的的顺序有关。相反析构函数的序有关。相反析构函数的执行与构行与构函数的函数的顺序相反。序相反。4.6.34.6.3虚基虚基类如果一个派生如果一个派生类的基的基类是从一个共同的基是从一个共同的基类派生出来的,那么派派生出来的,那么派生生类的的对象就是从底象就是从底层基基类的的间接派生,它会出接派生,它会出
20、现多个基多个基类的的拷拷贝,程序中如何,程序中如何进行分辨呢?一种方法是利用作用域运算符,行分辨呢?一种方法是利用作用域运算符,即在即在访问基基类的成的成员时明确指出要明确指出要访问的是哪一个基的是哪一个基类的数据的数据成成员。另一种方法是利用虚基类。虚基类是让基类只有一个拷另一种方法是利用虚基类。虚基类是让基类只有一个拷贝,程序中的访问就不会出现访问的不确定性。虚基类在派生贝,程序中的访问就不会出现访问的不确定性。虚基类在派生类中声明,其格式为:类中声明,其格式为:class 派生派生类名:名:virtual 继承方式承方式 基基类虚基虚基类的声明与普通的的声明与普通的继承形式相同,只不承形
21、式相同,只不过要在要在继承方式的前承方式的前面添加关面添加关键字:字:“virtual”。当使用虚基。当使用虚基类时,基,基类只有一个只有一个拷拷贝,程序中的,程序中的访问具有确定性。具有确定性。4.74.7多多态的基本概念的基本概念程序的多程序的多态性是指不同的性是指不同的对象收到相同的消息而作出不同的象收到相同的消息而作出不同的动作。多作。多态性包括运行性包括运行时的多的多态性和性和编译时的多的多态性。性。编译时的多的多态性是指性是指编译时的多的多态,通,通过函数重函数重载和运算符和运算符重重载来来实现。运行。运行时的多的多态则通通过继承和虚函数来承和虚函数来实现。1编译时的多的多态性性2
22、运行运行时的多的多态性性4.84.8函数重函数重载和运算符重和运算符重载函数重函数重载和运算符重和运算符重载可以可以实现编译时的多的多态性,从而可以性,从而可以动态的决定程序的的决定程序的动作。函数重作。函数重载可以使程序可以使程序设计更加灵更加灵活。运算符重活。运算符重载利用运算符函数来利用运算符函数来实现。4.8.14.8.1函数重函数重载派生派生类可以改写基可以改写基类的成的成员函数,从而函数,从而实现新的功能。新的功能。这就就是函数重是函数重载。函数重。函数重载后,程序后,程序员使用派生使用派生类的的对象可以象可以访问基基类或者是派生或者是派生类的成的成员函数。函数重函数。函数重载提高
23、了程序提高了程序设计的灵活性。的灵活性。4.8.24.8.2运算符重运算符重载在在C+中,除了中,除了对、可以、可以对函数函数进行重行重载外,外,还可以可以对运算符运算符进行重行重载。运算符的重运算符的重载通通过创建运算符函数建运算符函数operator来来实现。运算符重。运算符重载定定义了重了重载的运算符的操作。函数的运算符的操作。函数ooperator的操作的操作对象是一个象是一个类,同,同时operator可以是可以是这个个类的成的成员函数,可以是函数,可以是类的友元函数。的友元函数。运算符重运算符重载在在实际运用中有十分重要的意运用中有十分重要的意义,例如复数的四,例如复数的四则运算就
24、可以运算就可以借助运算符重借助运算符重载来来实现。运算符重。运算符重载包括两种形式,一是重包括两种形式,一是重载为类的的成成员函数,一是重函数,一是重载为类的友元函数。其形式如下:的友元函数。其形式如下:1重重载为类的成的成员函数:函数:函数函数类型型 operator 运算符(参数表)运算符(参数表)2重重载为友元函数:友元函数:friend 函数函数类型型 operator 运算符(参数表)运算符(参数表)4.94.9虚函数虚函数虚函数是重虚函数是重载的另一种表的另一种表现形式,它提供了一种形式,它提供了一种动态机制,机制,使程序运行更加灵活。一个基使程序运行更加灵活。一个基类的指的指针可
25、以指向派生可以指向派生类的的对象,但是利用基象,但是利用基类指指针调用用类的函数的函数时仍然仍然调用的是基用的是基类的成的成员函数。例如下面的例子。函数。例如下面的例子。4.104.10本章本章实例例类的使用的使用上面介上面介绍了了继承、多承、多态和重和重载的基本概念和使用方法。的基本概念和使用方法。C+作作为面向面向对象的程序象的程序设计语言,言,继承、多承、多态和重和重载的出的出现使使C+面向面向对象的特点体象的特点体现的更加明确。本的更加明确。本节给出几个例出几个例子。子。【示例示例4.26】创建复数建复数类,利用运算符重,利用运算符重载,实现其加法和其加法和减法。减法。4.114.11
26、小小结继承、封装和多承、封装和多态是面向是面向对象程序象程序设计的三大特性。本章的三大特性。本章详细介介绍了了C+的面向的面向对象程序象程序设计理理论。介。介绍了了类的基本的基本概念和基本操作。概念和基本操作。对派生派生类和基和基类的构造函数和析构函数的构造函数和析构函数的的执行行顺序序进行分析。行分析。讨论了如何通了如何通过虚函数虚函数实现多多态,介介绍了了纯虚函数将接口与虚函数将接口与实现进行分离。行分离。Visual C+提供提供类库,其是一整套的,其是一整套的类,掌握,掌握类的的继承、封装和多承、封装和多态是利是利用用MFC进行程序行程序设计的基的基础。4.124.12习题1构造函数和析构函数的作用是什么?写出其基本性构造函数和析构函数的作用是什么?写出其基本性质。2什么是友元?什么是友元函数和友元什么是友元?什么是友元函数和友元类?3继承方式有哪几种?每种方式的派生承方式有哪几种?每种方式的派生类对基基类成成员的的继承性如何?承性如何?4派生派生类的构造函数和析构函数的构造的构造函数和析构函数的构造规则如何?其如何?其执行行顺序又是如何?序又是如何?5虚函数与多虚函数与多态性有什么关系?性有什么关系?6虚函数在派生虚函数在派生类中的特征是否被中的特征是否被继承?承?