面向对象程序设计(C++语言)三课件.ppt

上传人(卖家):晟晟文业 文档编号:4941486 上传时间:2023-01-27 格式:PPT 页数:199 大小:1.51MB
下载 相关 举报
面向对象程序设计(C++语言)三课件.ppt_第1页
第1页 / 共199页
面向对象程序设计(C++语言)三课件.ppt_第2页
第2页 / 共199页
面向对象程序设计(C++语言)三课件.ppt_第3页
第3页 / 共199页
面向对象程序设计(C++语言)三课件.ppt_第4页
第4页 / 共199页
面向对象程序设计(C++语言)三课件.ppt_第5页
第5页 / 共199页
点击查看更多>>
资源描述

1、李爱华 程磊 编著清华大学出版社同名教材配套电子教案20102010年年 2 2月月面向对象程序设计(面向对象程序设计(C+语言)语言)32第二部分第二部分 面向对象的程序设计面向对象的程序设计 第第3章类和对象章类和对象(一一)第第4章类和对象章类和对象(二二)第第5章继承和派生章继承和派生第第6章虚函数与多态性章虚函数与多态性第第7章运算符重载章运算符重载第第8章模板章模板第第9章标准模板库章标准模板库STL第第10章章 C+语言的输入和输出语言的输入和输出3第第5章继承和派生章继承和派生本章重点:本章重点:v继承与派生的概念;继承与派生的概念;v派生类的构造函数和析构函数的执行顺序与规派

2、生类的构造函数和析构函数的执行顺序与规则;则;v多继承的声明与实现;多继承的声明与实现;v基类成员访问原则;基类成员访问原则;v赋值兼容性;赋值兼容性;v虚基类的概念虚基类的概念;45.1继承与派生的概念继承与派生的概念 v继承继承是面向对象程序设计中重要的特性。是面向对象程序设计中重要的特性。v继承主要是指在己有类的或称为继承主要是指在己有类的或称为基类基类的基础上的基础上创建新类的过程,这个新类就是创建新类的过程,这个新类就是派生类派生类。v派生类自动的包含了基类的成员,包括所有的派生类自动的包含了基类的成员,包括所有的数据和操作,而且它还可以增加自身新的成员数据和操作,而且它还可以增加自

3、身新的成员5在在C+中,一个派生类可以从一个基类派生,也可以从多个基类派生,从一个基中,一个派生类可以从一个基类派生,也可以从多个基类派生,从一个基类派生的称为单继承,如图类派生的称为单继承,如图5.1。图。图5.2中的树型结构图可以体现学生体系的中的树型结构图可以体现学生体系的概念。概念。图图5.1 5.1 单继承单继承 图图5.2 5.2 类的层次树型结构图类的层次树型结构图 6v一个派生类从两个或多个基类派生则称为多继承,如图一个派生类从两个或多个基类派生则称为多继承,如图5.3所示,它使一个所示,它使一个类可以融合了多个类的特征,例如在现实生活中的在职研究生的概念,他类可以融合了多个类

4、的特征,例如在现实生活中的在职研究生的概念,他是在职人员,又是研究生,如图是在职人员,又是研究生,如图5.4所示,从图中还可以看到一个有趣的现所示,从图中还可以看到一个有趣的现象,在职人员类本身是单继承的基类,教师和职员都是它的具体子类,而象,在职人员类本身是单继承的基类,教师和职员都是它的具体子类,而其又是在职研究生的多重基类,提供在职人员的基本特征。其又是在职研究生的多重基类,提供在职人员的基本特征。图图5.3 多继承多继承 图图5.4 单继承与多继承单继承与多继承 7继承机制除了支持软件复用外,还具备以下三个作继承机制除了支持软件复用外,还具备以下三个作用:用:v对事物进行分类。对事物进

5、行分类。v支持软件的增量开发。支持软件的增量开发。v对概念进行组合。对概念进行组合。8v前面的知识中,我们学习了如何定义类和如何实现类的抽象与封装,通常在不同的类中,数据前面的知识中,我们学习了如何定义类和如何实现类的抽象与封装,通常在不同的类中,数据成员和函数成员都是不同的,但对于某些特定的问题,有时候两个类的基本或大部分内容是相成员和函数成员都是不同的,但对于某些特定的问题,有时候两个类的基本或大部分内容是相同的,在图同的,在图5.2中给出了学生体系的概念,我们利用现有知识可以首先声明了一类中给出了学生体系的概念,我们利用现有知识可以首先声明了一类来描述学生这来描述学生这一基本概念一基本概

6、念,如下:,如下:class Student private:int number;char name20;public:Student()number=0;name0=0;Void SetValue(int n,char*s1)number=n;Strcpy(name,s1);void Print()cout”Number:”numberendl;cout”Name:”nameendl;;9v如果现在需要一个新类如果现在需要一个新类UGStudent来描述大学生概念,除上述的基本成员外,还需来描述大学生概念,除上述的基本成员外,还需要用到年龄、年级等信息,我们可以如下定义此类:要用到年龄、年

7、级等信息,我们可以如下定义此类:class UGStudent private:int number;char name20;int age;int grade;public:void Print()cout”Number:”numberendl;cout”Name:”nameendl;cout”Age:”ageendl;cout”Grade:”gradeendl;;105.2 派生类的声明派生类的声明 v在在C+中类的继承关系可以用如下语法表示:中类的继承关系可以用如下语法表示:class 派生类名派生类名:继承方式继承方式 基类名基类名 派生类成员声明派生类成员声明;v需要注意的是,基类的

8、构造函数和析构函数不需要注意的是,基类的构造函数和析构函数不能被派生类继承,派生类若要初始化基类的数能被派生类继承,派生类若要初始化基类的数据成员必须在构造函数中初始化。据成员必须在构造函数中初始化。11【例【例5.1】用继承重新定义】用继承重新定义UGStudent类。类。/*05_01.cpp*/class UGStudent:public Studentprivate:int age;int grade;public:UGStudent()SetValue(0,”);age=0;grade=0;UGStudent(int n,char*s1,int a,int g)SetValue(n,

9、s1);age=a;grade=g;void PrintExtra()cout”Age:”ageendl;cout”Grade:”gradeendl;12用主函数进行测试用主函数进行测试:int main()UGStudent st1(100,”wang”,18,1);st1.Print();/调用基类的函数调用基类的函数st1.PrintExtra();/调用派生类新定义的函数调用派生类新定义的函数return 0;13Number:100Name:wangAge:18Grade:1程序的运行结果为:程序的运行结果为:14图图5.5 基类与派生类中的成员基类与派生类中的成员 155.3 派生

10、类的访问属性派生类的访问属性 v类的成员可以分为类的成员可以分为public(公有)、公有)、protected(保护)和保护)和private(私有)三种访问权限。私有)三种访问权限。v类的非静态成员函数可以访问类中的所有成员,类的非静态成员函数可以访问类中的所有成员,但是通过类的但是通过类的“对象对象.成员成员”方式(在类的作用方式(在类的作用域之外),则只能访问该类的公有成员。域之外),则只能访问该类的公有成员。v类的继承方式有公有继承(类的继承方式有公有继承(public)、)、保护继保护继承(承(protected)和私有继承(和私有继承(private)三种。三种。v不同的继承方式

11、,导致原有基类成员在派生类不同的继承方式,导致原有基类成员在派生类中的访问属性也有所不同。中的访问属性也有所不同。16表表5.1不同继承方式下的访问控制权限不同继承方式下的访问控制权限基类成员的权限继承方式publicprotectedprivatepublic在派生类中为public在派生类中为protected在派生类中为private派生类的成员函数和类的作用域之外,都可以直接访问派生类的成员函数可以直接访问派生类的成员函数可以直接访问protected在派生类中为protected在派生类中为protected在派生类中为private派生类的成员函数可以直接访问派生类的成员函数可以直

12、接访问派生类的成员函数可以直接访问private在派生类中被隐藏,无法访问在派生类中被隐藏,无法访问在派生类中被隐藏,无法访问任何方式都不能直接访问,但可以通过基类的public、protected成员函数间接访问任何方式都不能直接访问,但可以通过基类的public、protected成员函数间接访问访问任何方式都不能直接访问,但可以通过基类的public、protected成员函数间接访问访问17v对于静态成员来说,与普通成员函数组合,将对于静态成员来说,与普通成员函数组合,将产生以下两种情况:产生以下两种情况:(1)派生类中静态函数对基类中静态成员的访问。派生类中静态函数对基类中静态成员的

13、访问。(2)派生类的普通成员函数要访问基类中的静态成员。派生类的普通成员函数要访问基类中的静态成员。v静态成员的访问控制变化完全遵循表静态成员的访问控制变化完全遵循表5.1的规则,的规则,这两种情况和派生类中普通成员函数访问基类这两种情况和派生类中普通成员函数访问基类中普通成员没有区别。中普通成员没有区别。18【例【例5.2】公有继承时的访问控制权限。】公有继承时的访问控制权限。/*05_02.cpp*/#includeusing namespace std;class Base private:int a;void fun1()coutaendl;protected:int b;void f

14、un2()coutcendl;public:int c;void fun3()coutbendl;void seta(int i)/修改私有成员修改私有成员a的值的值 a=i;int geta()/返回私有成员返回私有成员a的值的值 return a;Base(int i,int j,int k)/基类的构造函数基类的构造函数 a=i;b=j;c=k;19class Sub:public Base private:int d;public:Sub(int i,int j,int k,int m):Base(i,j,k)/派生类构造函数派生类构造函数 d=m;void test()/coutae

15、ndl;/错误,无法访问基类的私有成员错误,无法访问基类的私有成员coutb endl;/正确,可以访问基类的保护成员正确,可以访问基类的保护成员coutc endl;/正确,可以访问基类的公有成员正确,可以访问基类的公有成员/fun1();/错误,无法访问基类的私有成员错误,无法访问基类的私有成员fun2();/正确,可以访问基类的保护成员正确,可以访问基类的保护成员fun3();/正确,可以访问基类的公有成员正确,可以访问基类的公有成员seta(10);/正确,间接访问基类成员正确,间接访问基类成员acout d endl;/正确,可以访问派生类的私有成员正确,可以访问派生类的私有成员;2

16、0int main()Base b1(5,6,7);/cout b1.a;/错误,无法访问对象的私有成员错误,无法访问对象的私有成员/coutb1.b;/错误,错误,无法访问对象的保护成员无法访问对象的保护成员coutb1.cendl;/正确,可以访问对象的公有成员正确,可以访问对象的公有成员coutb1.geta()endl;/正确,间接访问对象的私有成员正确,间接访问对象的私有成员aSub s1(11,15,19,22);s1.test();/正确,可以访问对象的公有成员正确,可以访问对象的公有成员s1.c=200;/正确,可以访问对象的公有成员正确,可以访问对象的公有成员s1.fun3(

17、);/正确,可以访问对象的公有成员正确,可以访问对象的公有成员return 0;215.4 派生类的构造函数和析构函数派生类的构造函数和析构函数 v在继承机制中,基类的构造函数和析构函数是在继承机制中,基类的构造函数和析构函数是不能继承的。不能继承的。v派生类的构造函数负责对来自基类数据成员和派生类的构造函数负责对来自基类数据成员和新增加的数据成员进行初始化。新增加的数据成员进行初始化。v所以在执行派生类的构造函数时,需要调用基所以在执行派生类的构造函数时,需要调用基类的构造函数。类的构造函数。225.4.1 派生类构造函数和析构函数的执行顺序派生类构造函数和析构函数的执行顺序 v通过继承,派

18、生类得到了基类的成员,因此派生类对象通过继承,派生类得到了基类的成员,因此派生类对象中既包括自身类的数据成员还包括通过继承从基类中得中既包括自身类的数据成员还包括通过继承从基类中得到的数据成员。到的数据成员。v在派生类中还可用其他类来定义对象作为成员,又涉及在派生类中还可用其他类来定义对象作为成员,又涉及到派生类中对象成员的构造问题,则当用派生类定义对到派生类中对象成员的构造问题,则当用派生类定义对象后,派生类对象、对象成员、基类对象的构造函数的象后,派生类对象、对象成员、基类对象的构造函数的调用顺序如下:调用顺序如下:基类的构造函数。基类的构造函数。对象成员的构造函数(如果有的话),有多个时

19、按声明的顺序。对象成员的构造函数(如果有的话),有多个时按声明的顺序。派生类的构造函数。派生类的构造函数。23【例【例5.3】派生类构造实例。】派生类构造实例。/*05_03.cpp*/#includeusing namespace std;class Bpublic:B()cout”Construct B”endl;class Cpublic:C()cout”Construct C”endl;class D:public Bprivate:C c1;public:D()cout”Construct D”endl;int main()D d1;return 0;24construct BCon

20、struct CConstruct D程序的运行结果为:程序的运行结果为:25v析构函数与构造函数执行的顺相反,将按如下析构函数与构造函数执行的顺相反,将按如下顺序执行:顺序执行:(1)派生类的构造函数;派生类的构造函数;(2)对象成员的构造函数(如果有的话),有多个时对象成员的构造函数(如果有的话),有多个时与声明的顺序相反;与声明的顺序相反;(3)基类对象的析构函数。基类对象的析构函数。26对例对例5.3中的程序进行改造,为每一个类添加析构函数,然后再进行测试。中的程序进行改造,为每一个类添加析构函数,然后再进行测试。class Bpublic:B()cout”Construct B”en

21、dl;B()cout”Deconstruct B”endl;class Cpublic:C()cout”Construct C”endl;C()cout”Deconstruct C”endl;class D:public Bprivate:C c1;public:D()cout”Construct D”endl;D()cout”Deconstruct D”endl;int main()D d1;return 0;27Construct BConstruct CConstruct DDestruct DDestruct CDestruct B程序的运行结果为:程序的运行结果为:285.4.2 派

22、生类构造函数和析构函数的构造规则派生类构造函数和析构函数的构造规则 v在在C+中,类的机制非常清楚、严格地划分了中,类的机制非常清楚、严格地划分了各自的权限和责任。是哪个类的操作,必须由各自的权限和责任。是哪个类的操作,必须由那个类调用;那个类调用;v是谁的对象,就必须由该类的构造函数来完成是谁的对象,就必须由该类的构造函数来完成对其构造的工作。对其构造的工作。v因此,对派生类中基类成员的构造,必须由基因此,对派生类中基类成员的构造,必须由基类构造函数完成,而不能由派生类的构造函数类构造函数完成,而不能由派生类的构造函数越权去构造。越权去构造。v派生类构造函数主要负责调用基类构造函数并派生类构

23、造函数主要负责调用基类构造函数并提供基类构造函数所需的参数。提供基类构造函数所需的参数。29下面分两种情况讨论派生类对象的构造:下面分两种情况讨论派生类对象的构造:1如基类中定义了默认构造函数,且该默认构造函如基类中定义了默认构造函数,且该默认构造函数能够完成派生类对象中基类成员的构造,则派数能够完成派生类对象中基类成员的构造,则派生类构造函数无需显式调用基类构造函数,直接生类构造函数无需显式调用基类构造函数,直接调用基类的默认构造函数即可,这是一种较为简调用基类的默认构造函数即可,这是一种较为简单的情况,单的情况,例例5.3中的继承就属于此类情况,下面的例子也可中的继承就属于此类情况,下面的

24、例子也可以说明这一点。以说明这一点。30【例【例5.4】分析下面程序的输出结果。】分析下面程序的输出结果。/*05_04.cpp*/#includeusing namespace std;class Basepublic:Base()a=0;Base(int i)a=i;protected:int a;class Derived:public Basepublic:Derived()b=0;Derived(int i)b=i;void Print()couta=a,b=bendl;private:int b;31int main()Derived d1;Derived d2(12);d1.Pr

25、int();d2.Print();return 0;32a=0,b=0a=0,b=12程序的运行结果为:程序的运行结果为:332若基类中定义了有参数的构造函数,或者所定义的默认构若基类中定义了有参数的构造函数,或者所定义的默认构造函数不能完成基类成员的构造,则必须通过派生类构造造函数不能完成基类成员的构造,则必须通过派生类构造函数显式向调用基类的构造函数,向带参数的构造函数传函数显式向调用基类的构造函数,向带参数的构造函数传递参数,这需要用到递参数,这需要用到“成员初始化列表成员初始化列表”的语法。的语法。v 另外,对于派生类中普通数据成员的初始化,以及对象成另外,对于派生类中普通数据成员的初

26、始化,以及对象成员的构造也可以放在成员初始化列表中完成。员的构造也可以放在成员初始化列表中完成。v此时这些以逗号隔开的基类构造函数调用数据成员初始化此时这些以逗号隔开的基类构造函数调用数据成员初始化和构造的放置顺序可以是任意的。和构造的放置顺序可以是任意的。因此派生类的构造函数定义一般格式如下:因此派生类的构造函数定义一般格式如下:派生类名派生类名(参数列表参数列表):基类构造函数基类构造函数(参数列表参数列表1),子对象成员子对象成员1(参数列(参数列表)表)派生类构造函数体派生类构造函数体34【例【例5.5】派生类构造函数举例。】派生类构造函数举例。/*05_05.cpp*/#includ

27、e#include using namespace std;class Date/日期类日期类private:int year,mon,day;/年、月、日成员变量年、月、日成员变量public:Date(int y=2009,int m=6,int d=10)/构造函数构造函数year=y;mon=m;day=d;void Print()/输出数据,格式为:年输出数据,格式为:年-月月-日日coutyear-mon-dayendl;35class Student/定义学生基类定义学生基类 protected:int number;/数据成员数据成员char name20;char sex;p

28、ublic:Student()/重定义的默认构造函数重定义的默认构造函数number=0;strcpy(name,No name);/默认名字默认名字sex=M;/默认性别,男性默认性别,男性(male)dStudent(int n,char*s,char x)/带参数的构造函数带参数的构造函数number=n;strcpy(name,s);sex=x;36/大学生派生类大学生派生类class UGStudent:public Student public:UGStudent(int n,char*s,char x,int a,int y,int m,int d):Student(n,s,x)

29、,birth(y,m,d)age=a;UGStudent()/此处省略了此处省略了Student()调用调用age=0;void Print()/输出信息输出信息coutnumber:numberendl;coutname:nameendl;coutsex:sexendl;coutage:ageendl;coutbirthday:;birth.Print();private:int age;Date birth;/对象成员对象成员;37/主函数主函数int main()UGStudent st1;/用派生的默认构造函数定义对象用派生的默认构造函数定义对象UGStudent st2(1001,Z

30、hang,F,20,2009,6,11);/带参数构造带参数构造st1.Print();st2.Print();return 0;38number:0name:No namesex:Mage:0birthday:2009-6-10number:1001name:Zhangsex:Fage:20birthday:2009-6-11程序的运行结果为:程序的运行结果为:395.5 多继承多继承 5.5.1 多继承的声明多继承的声明 v多继承下派生类的声明格式如下:多继承下派生类的声明格式如下:class 派生类名派生类名:继承方式继承方式1 基类名,继承方式基类名,继承方式2 基类名基类名2 2 派

31、生类类体派生类类体;v其中,继承方式其中,继承方式1、继承方式、继承方式2 是三种继承方式:是三种继承方式:public、private和和protected 之一。之一。40如下为最基本的定义形式:如下为最基本的定义形式:class B1;class B2;class D:public B1,public B2;41图图5.6 多继承类多继承类D中的成员中的成员 425.5.2 多继承的构造函数与析构函数多继承的构造函数与析构函数 v在多继承的情况下,派生类的构造函数格式如下:在多继承的情况下,派生类的构造函数格式如下:派生类名(参数列表)派生类名(参数列表):基类名基类名1(参数表参数表1

32、),基类名基类名2(参数表参数表2),子对象名子对象名(参数表参数表n)派生类构造函数体;派生类构造函数体;43v多继承下派生类的构造函数与单继承下派生类多继承下派生类的构造函数与单继承下派生类构造函数相似,它必须同时负责该派生类所有构造函数相似,它必须同时负责该派生类所有基类构造函数的调用同时,派生类的参数个数基类构造函数的调用同时,派生类的参数个数必须包含完成所有基类初始化所需的参数个数。必须包含完成所有基类初始化所需的参数个数。v派生类构造函数执行顺序是先执行所有基类的派生类构造函数执行顺序是先执行所有基类的构造函数,再执行派生类本身构造函数。构造函数,再执行派生类本身构造函数。v处于同

33、一层次的各基类构造函数的执行顺序取处于同一层次的各基类构造函数的执行顺序取决于声明派生类时所指定的各基类顺序,与派决于声明派生类时所指定的各基类顺序,与派生类构造函数中所定义的成员初始化列表的各生类构造函数中所定义的成员初始化列表的各项顺序无关。项顺序无关。v另外,析构函数的调用顺序则与构造函数完全另外,析构函数的调用顺序则与构造函数完全相反。相反。44【例【例5.6】多继承举例。】多继承举例。/*05_06.cpp*/#include#include using namespace std;/定义研究生基类定义研究生基类class GStudent protected:int number;

34、/学号学号 char name20;/名字名字char sex;/性别,男性:性别,男性:M,女性:女性:Fpublic:GStudent(int n,char*s,char x)/带参数的构造函数带参数的构造函数number=n;strcpy(name,s);sex=x;coutConstruct GStudent.endl;GStudent()/析构函数析构函数 coutDestruct GStudent.endl;45class Employee/职员类职员类protected:char ename20;/职员名字职员名字char jobname20;/工作名工作名public:Empl

35、oyee(char*sn,char*sj)/构造函数构造函数strcpy(ename,sn);strcpy(jobname,sj);coutConstruct Employee.endl;Employee()/析构函数析构函数 coutDestruct Employee.endl;46/在职研究生类,从两个基类派生在职研究生类,从两个基类派生class GStudentHasJob:public GStudent,public Employee public:GStudentHasJob(int n,char*s,char x,char*sj):GStudent(n,s,x),Employee

36、(s,sj)coutConstruct GStudentHasJob.endl;GStudentHasJob()coutDestruct GStudentHasJob.endl;void Print()/输出信息输出信息coutnumber:numberendl;coutname:nameendl;coutsex:sexendl;coutjob:jobnameendl;47/主函数主函数int main()/定义一个在职研究生对象,并对其初始化定义一个在职研究生对象,并对其初始化GStudentHasJob st(1001,zhang,F,teacher);st.Print();return

37、0;48Construct GStudent.Construct Employee.Construct GStudentHasJob.number:1001name:zhangsex:Fjob:teacherDestruct GStudentHasJob.Destruct Employee.Destruct GStudent.程序的运行结果为:程序的运行结果为:495.6 基类成员访问和赋值兼容性基类成员访问和赋值兼容性 5.6.1基类成员名的限定访问和名字覆盖基类成员名的限定访问和名字覆盖 v若多个基类中定义有同名成员,则派生类对这若多个基类中定义有同名成员,则派生类对这些同名成员的访问可能

38、存在冲突。些同名成员的访问可能存在冲突。v为避免可能出现的成员访间冲突,需要用成员为避免可能出现的成员访间冲突,需要用成员名限定的方法显式地指定要访问的成员。名限定的方法显式地指定要访问的成员。50【例【例5.7】成员访问冲突。】成员访问冲突。/*05_07.cpp*/#include using namespace std;class MP3Player/mp3播放器类播放器类public:void Play()/播放音乐操作播放音乐操作 coutPlay mp3 music.endl;class VideoPlayer/视频播放器类视频播放器类public:void Play()/播放视频

39、操作播放视频操作 coutPlay video.endl;/新型的新型的mp4播放器类播放器类class MP4Player:public MP3Player,public VideoPlayerpublic:/*/;51int main()MP4Player mp4;/mp4.Play();/去掉注释,本行将产生去掉注释,本行将产生Play()函数访问不明确的错误函数访问不明确的错误mp4.MP3Player:Play();mp4.VideoPlayer:Play();return 0;52Play mp3 music.Play video.程序的运行结果为:程序的运行结果为:53v对于多继

40、承,如果在不同的基类中定义了同名对于多继承,如果在不同的基类中定义了同名的成员,在派生类中要区分成员的来源,就必的成员,在派生类中要区分成员的来源,就必须使用须使用成员名限定方法,即在成员名前加上各成员名限定方法,即在成员名前加上各自基类的访问域限制即可。自基类的访问域限制即可。54【例【例5.8】多继承中成员限定法。】多继承中成员限定法。/*05_08.cpp*/#include using namespace std;class B1/基类基类B1public:int m;/成员变量成员变量mB1()/构造函数构造函数 m=0;class B2/基类基类B2public:int m;/成员

41、变量成员变量mB2()/构造函数构造函数 m=100;55class D:public B1,public B2/派生类派生类 Dpublic:void Test()/coutmendl;/此语句将引起二义性错误此语句将引起二义性错误coutB1:m=B1:mendl;/输出基类输出基类B1中的成员中的成员m的值的值coutB2:m=B2:mendl;/输出基类输出基类B2中的成员中的成员m的值的值;int main()/主函数主函数D d1;/派生类对象派生类对象d1.Test();return 0;56B1:m=0B2:m=100程序的运行结果为:程序的运行结果为:575.6.2名字覆盖名

42、字覆盖 v当派生类中定义有与基类中同名的成员时,则当派生类中定义有与基类中同名的成员时,则从基类中继承得到的成员被派生类的同名成员从基类中继承得到的成员被派生类的同名成员覆盖,派生类对基类成员的直接访问将被派生覆盖,派生类对基类成员的直接访问将被派生类中该成员取代,为访问基类成员,必须采用类中该成员取代,为访问基类成员,必须采用成员名限定方法。成员名限定方法。58【例【例5.9】成员访问冲突。】成员访问冲突。/*05_09.cpp*/#include using namespace std;class Circle/定义圆类定义圆类 protected:float radius;/半径半径pu

43、blic:Circle(float r)/构造函数构造函数radius=r;float Area()/求圆面积求圆面积 return 3.14f*radius*radius;59class Cylinder:public Circle/圆柱体派生类圆柱体派生类private:float height;/高度高度public:Cylinder(float r,float h):Circle(r)/构造函数构造函数height=h;float Area()/求圆柱体面积,覆盖了基类的求圆柱体面积,覆盖了基类的Area()函数函数float botarea=0,sidearea=0;botarea=

44、Circle:Area()*2;/底面积底面积*2sidearea=2*3.14f*radius*height;/侧面积侧面积return botarea+sidearea;float Volume()/圆柱体积圆柱体积return Circle:Area()*height;/基类求面积乘高度基类求面积乘高度;60int main()Cylinder cr1(10,5);/定义圆柱体对象定义圆柱体对象coutBottomArea=cr1.Circle:Area()endl;/访问基类成员访问基类成员coutArea=cr1.Area()endl;/访问派生类成员访问派生类成员coutVolum

45、e=cr1.Volume()endl;return 0;61BottomArea=314Area=942Volume=1570程序的运行结果为:程序的运行结果为:62v从上述程序可以看出,用派生类对象访问与基从上述程序可以看出,用派生类对象访问与基类中同名的成员时,会调用本类中的成员,而类中同名的成员时,会调用本类中的成员,而不会访问到基类成员。为访问到基类的同名成不会访问到基类成员。为访问到基类的同名成员,需要以成员名限定的方法来指明,如在员,需要以成员名限定的方法来指明,如在Cylinder类中的求面积和体积函数就用到了基类类中的求面积和体积函数就用到了基类的的Circle:Area()函

46、数。函数。v另外,要注意的一点是,在派生类如果定义了另外,要注意的一点是,在派生类如果定义了和基类中同名的函数,则基类中所有的同名的和基类中同名的函数,则基类中所有的同名的重载函数都将被覆盖,即在派生类中或通过派重载函数都将被覆盖,即在派生类中或通过派生类对象都无法直接访问基类的任何一个同名生类对象都无法直接访问基类的任何一个同名函数,如图函数,如图5.7中定义了一个基类和派生类,中定义了一个基类和派生类,63图图5.7 派生类对基类的名字覆盖派生类对基类的名字覆盖 645.6.3赋值兼容规则赋值兼容规则 v在派生类对象和基类对象之间赋值时需要注意在派生类对象和基类对象之间赋值时需要注意赋值的

47、方向,即这些赋值操作需要满足赋值兼赋值的方向,即这些赋值操作需要满足赋值兼容规则。赋值兼容规则包括:容规则。赋值兼容规则包括:(1)基类对象可以赋值给基类对象,也可以把派生)基类对象可以赋值给基类对象,也可以把派生类对象赋值给基类对象。类对象赋值给基类对象。(2)基类指针可以指向基类对象,也可以指向派生)基类指针可以指向基类对象,也可以指向派生类对象。类对象。(3)基类引用可以指向基类对象,也可以指向派生)基类引用可以指向基类对象,也可以指向派生类对象。类对象。65v例如,有基类例如,有基类Base和其派生类和其派生类Derived,可以定义相应可以定义相应的对象、指针:的对象、指针:Base

48、 b1;Base*pb;Derived d1;v根据赋值兼容规则,在基类根据赋值兼容规则,在基类BaseBase对象可以出现的任何地对象可以出现的任何地方都可以用派生类方都可以用派生类DerivedDerived对象来替代。对象来替代。(1)派生类对象可以赋值给基类对象,即派生类对象中来自基类成员,)派生类对象可以赋值给基类对象,即派生类对象中来自基类成员,逐个赋值给基类对象的成员:逐个赋值给基类对象的成员:b1=d1;(2)派生类的对象也可以初始化基类对象的引用:派生类的对象也可以初始化基类对象的引用:Base&rb=d1;(3)基类的指针赋值为派生类对象的地址:基类的指针赋值为派生类对象的

49、地址:pb=&d1;66【例【例5.10】赋值兼容实例。赋值兼容实例。/*05_10.cpp*/#includeusing namespace std;class Base/基类基类Baseprotected:int member;public:Base()member=0;void Show()/共有成员函数共有成员函数 coutBase:Show():memberendl;class Derived1:public Base/第第1个派生类个派生类Derived1public:Derived1(int a)member=a;void Show()/重写共有成员函数重写共有成员函数Show

50、coutDerived1:Show():memberendl;67class Derived2:public Derived1 /第第2个派生类个派生类Derived2public:Derived2(int a):Derived1(a)void Show()/重写共有成员函数重写共有成员函数Show coutDerived2:Show():memberShow();void Test(Base&br)/测试函数,用基类引用作参数测试函数,用基类引用作参数 br.Show();int main()/主函数主函数Base b0;/基类基类Base对象对象Derived1 d1(5);/派生类派生类

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 办公、行业 > 各类PPT课件(模板)
版权提示 | 免责声明

1,本文(面向对象程序设计(C++语言)三课件.ppt)为本站会员(晟晟文业)主动上传,163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。
2,用户下载本文档,所消耗的文币(积分)将全额增加到上传者的账号。
3, 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(发送邮件至3464097650@qq.com或直接QQ联系客服),我们立即给予删除!


侵权处理QQ:3464097650--上传资料QQ:3464097650

【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。


163文库-Www.163Wenku.Com |网站地图|