面向对象程序设计—第六章_第1页
面向对象程序设计—第六章_第2页
面向对象程序设计—第六章_第3页
面向对象程序设计—第六章_第4页
面向对象程序设计—第六章_第5页
已阅读5页,还剩70页未读 继续免费阅读

下载本文档

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

文档简介

1、第六章第六章 派生类和继承派生类和继承6.1、派生类的概念、派生类的概念6.2、派生类的构造函数和析构函数、派生类的构造函数和析构函数6.3、多重继承、多重继承C+的精华的精华6.1、派生类的概念、派生类的概念1、派生类的概念、派生类的概念2、为什么使用派生类、为什么使用派生类3、派生类的声明方法、派生类的声明方法4、私有派生的特性、私有派生的特性5、公有派生的特性、公有派生的特性6、保护成员在公、私派生中的特性、保护成员在公、私派生中的特性6.1、派生类的概念、派生类的概念1、派生类、派生类C+中使用继承性进行代码重用的方式就是中使用继承性进行代码重用的方式就是派生派生继承继承是面向对象程序

2、设计支持是面向对象程序设计支持代码重用代码重用的重要机制的重要机制汽车客车货车运输汽车消防车洒水车专有汽车派生类在原有类的基础上创建新的类派生类在原有类的基础上创建新的类:(1)获得一个或多个获得一个或多个原有类中的函数和数据;原有类中的函数和数据;(2) 可以可以重新定义重新定义和和增加增加新的属性和方法新的属性和方法从而形成层次或等级关系从而形成层次或等级关系也便于对类进行组织也便于对类进行组织基类或者父类派生类或者子类6.1、派生类的概念、派生类的概念2、为什么使用派生类、为什么使用派生类class person private: char name10; int age; char s

3、ex; public: person(); void print();class employee private: char name10; int age; char sex; char department20; float salary; public: employee(); void print();employee类类与与person相比相比只是增加两个属性,其它相同只是增加两个属性,其它相同6.1、派生类的概念、派生类的概念3、 派生类的声明方法派生类的声明方法class 派生类名派生类名:派生方式派生方式 基类名基类名 /派生类中新的数据成员和成员函数派生类中新的数据成员和成

4、员函数 ;派生派生方式分为:方式分为:公有派生、私有派生、保护派生公有派生、私有派生、保护派生(1)基类成员到了派生类中后,访问权限是什么?基类成员到了派生类中后,访问权限是什么?(2) 对于这些基类成员,派生类的新成员能否访问?对于这些基类成员,派生类的新成员能否访问?public、private、protected带来两个问题:带来两个问题:6.1、派生类的概念、派生类的概念(1)公有派生中,基类中的公有成员在派生类是公有的,私有公有派生中,基类中的公有成员在派生类是公有的,私有成员在派生类是私有的成员在派生类是私有的(2) 私有派生中,基类中的私有派生中,基类中的所有成员所有成员在派生类

5、中是私有成员在派生类中是私有成员基类成员的访问权限基类成员的访问权限6.1、派生类的概念、派生类的概念基类基类公有公有成员成员基类基类私有私有成员成员基类基类派生派生类类基类基类公有公有成员成员基类基类私有私有成员成员新新公有公有成员成员新新私有私有成员成员公有派生公有派生基类基类公有公有成员成员基类基类私有私有成员成员基类基类派生派生类类基类基类私有私有成员成员基类基类私有私有成员成员新新公有公有成员成员新新私有私有成员成员私有派生私有派生分析:派生类新旧成员之间的访问权限如何?分析:派生类新旧成员之间的访问权限如何?6.1、派生类的概念、派生类的概念4、私有私有派生的特性派生的特性(1)私

6、有派生对基类成员的访问私有派生对基类成员的访问 基类所有的公有成员基类所有的公有成员都成为派生类的私有成员,他们能够都成为派生类的私有成员,他们能够被派生类的成员访问;被派生类的成员访问; 基类所有的私有成员基类所有的私有成员不能被派生类成员访问,但可以通过不能被派生类成员访问,但可以通过基类的公有成员函数访问基类的公有成员函数访问(2)外部函数对私有派生类、继承类的成员的访问外部函数对私有派生类、继承类的成员的访问 基类中的所有成员在派生类中都成为私有成员,外部函数基类中的所有成员在派生类中都成为私有成员,外部函数不能够访问不能够访问到了派生类中的成员到了派生类中的成员6.1、派生类的概念、

7、派生类的概念举例举例#include class base /定义基类定义基类 int x; public: void setx(int n) x=n; void showx() cout xendl; ;class derived : private base /定义私有派生类定义私有派生类 int y; public: void setxy(int n, int m) /设定类的属性的值设定类的属性的值 setx(n); /调用基类函数调用基类函数 y=m; 合法:合法:setx可被可被setxy访问访问6.1、派生类的概念、派生类的概念 void showxy() coutxyendl;

8、 /非法非法,不能访问,不能访问x;main() derived obj; obj.setx(10); /非法非法,外部不能对私有派生继承来的成员访问,外部不能对私有派生继承来的成员访问 obj.setxy(10,20); /合法合法 obj.showx(); /非法非法,外部不能对私有派生继承来的成员访问外部不能对私有派生继承来的成员访问 obj.showxy(); /合法合法 return 0;6.1、派生类的概念、派生类的概念5、公有公有派生的特性派生的特性公有派生时基类成员的可访问性在派生类中维持不变:公有派生时基类成员的可访问性在派生类中维持不变: 基类中的私有成员基类中的私有成员在

9、派生类仍是私有成员,不允许外部函数在派生类仍是私有成员,不允许外部函数和派生类的成员函数访问;和派生类的成员函数访问; 基类中的公有成员基类中的公有成员仍是派生类中的公有成员,外部函数和派仍是派生类中的公有成员,外部函数和派生类的成员可以直接访问生类的成员可以直接访问6.1、派生类的概念、派生类的概念举例举例#includeclass base /定义基类定义基类 int x;public: void setx(int n) x=n; void showx() cout xendl; ;class derived : public base /定义公有派生类定义公有派生类 int y;publ

10、ic: void sety(int n) y=n; void showy() coutyendl; / void showxy() coutxendl; coutyendl; ;非法非法6.1、派生类的概念、派生类的概念main() derived obj; obj.setx(10); /合法合法 obj.sety(20); /合法合法 obj.showx(); /合法合法 obj.showy(); /合法合法 return 0;6.1、派生类的概念、派生类的概念6、保护成员保护成员在公、私派生中的特性在公、私派生中的特性保护成员可以被派生类中的成员函数访问,但是对于保护成员可以被派生类中的成

11、员函数访问,但是对于外界是掩藏的外界是掩藏的(1)私有派生中:私有派生中: 基类的保护成员基类的保护成员成为派生类的私有成员,他们能够被派生成为派生类的私有成员,他们能够被派生类的成员访问,不能被外部函数访问;类的成员访问,不能被外部函数访问;(2)公有派生中:公有派生中: 基类的保护成员基类的保护成员成为派生类的保护成员,他们能够被派生成为派生类的保护成员,他们能够被派生类的成员访问,不能被外部函数访问;类的成员访问,不能被外部函数访问;访问性质在两种派生中一样访问性质在两种派生中一样原则:原则:对派生类相当于公有,对外部函数相当于私有对派生类相当于公有,对外部函数相当于私有6.1、派生类的

12、概念、派生类的概念举例举例#includeclass base /定义类定义类base protected: /定义保护成员定义保护成员 int a, b; public: void setab(int n,int m) /设定属性的值设定属性的值 a=n; b=m; ;class derived : public base /定义公有派生类定义公有派生类derive int c; public: void setc(int n) c=n; void showbc() cout b cendl; /允许访问派生类的成员允许访问派生类的成员b;private6.1、派生类的概念、派生类的概念ma

13、in() /主函数主函数 derived obj; /定义对象定义对象obj obj.setab(2,4); /设定基类保护成员的值设定基类保护成员的值 obj.setc(3); obj.showbc(); /显示对象的值显示对象的值 obj.b=3;/非法非法 return 0; 一般来说一般来说,将基类私有成员中需要提供给派生类访问,将基类私有成员中需要提供给派生类访问的成员定义为保护成员的成员定义为保护成员6.1、派生类的概念、派生类的概念总结:总结:继承方式继承方式publicpublic派生派生protectedprotected派生派生privateprivate派生派生publi

14、cpublic基类成员基类成员访问属性访问属性 派生类成员派生类成员访问属性访问属性publicpublicprotectedprotectedprivateprivateprotectedprotectedprivateprivate在派生类中隐藏在派生类中隐藏protectedprotectedprotectedprotectedprivateprivate在派生类中隐藏在派生类中隐藏privateprivateprivateprivateprivateprivate在派生类中隐藏在派生类中隐藏基类的成员可以访问,基类的成员可以访问,因此通过基类的公有成员间接访问因此通过基类的公有成员间接

15、访问(1)访问权限:访问权限:如果不显示指定继承方式,编译如果不显示指定继承方式,编译器默认为私有继承器默认为私有继承6.1、派生类的概念、派生类的概念(2)派生类除拥有基类成员外:派生类除拥有基类成员外:(a)可以可以增加增加新的数据成员和成员函数。新的数据成员和成员函数。(b)可以可以重新定义重新定义基类的成员函数。基类的成员函数。(c)可以可以修改修改现有成员的属性。现有成员的属性。6.2、派生类的构造函数和析构函数派生类的构造函数和析构函数1、研究派生类构造、析构函数的原因、研究派生类构造、析构函数的原因 因为派生类继承了基类的成员,所以在实例化派生因为派生类继承了基类的成员,所以在实

16、例化派生类对象时,必须调用基类的构造函数来初始化派生类对类对象时,必须调用基类的构造函数来初始化派生类对象中基类的成员象中基类的成员 当然也要调用派生类的构造函数当然也要调用派生类的构造函数需要研究两者的需要研究两者的如何调用、调用次序、参数传递如何调用、调用次序、参数传递关系等关系等 派生类既可以派生类既可以隐式隐式调用基类的构造函数,也可以在调用基类的构造函数,也可以在派生类的构造函数中派生类的构造函数中显式显式的调用基类的构造函数的调用基类的构造函数6.2、派生类的构造函数和析构函数派生类的构造函数和析构函数2、派生类构造函数和析构函数执行、派生类构造函数和析构函数执行顺序顺序创建派生类

17、对象创建派生类对象: (1)执行基类的构造函数执行基类的构造函数 (2)执行派生类的构造函数执行派生类的构造函数撤销派生类对象撤销派生类对象: 执行派生类的析构函数执行派生类的析构函数 执行基类的析构函数执行基类的析构函数6.2、派生类的构造函数和析构函数派生类的构造函数和析构函数3、派生类构造函数和析构函数的、派生类构造函数和析构函数的构造规则构造规则(1)基类的构造函数基类的构造函数没有参数没有参数,或者,或者没有显式地定义构造函数没有显式地定义构造函数的的时候,派生类可以不向基类传递参数,甚至可以不定义构造函数时候,派生类可以不向基类传递参数,甚至可以不定义构造函数(2)派生类派生类不能

18、继承不能继承基类中的构造函数和析构函数。基类中的构造函数和析构函数。当基类中当基类中带有参数的构造函数带有参数的构造函数的时候,派生类必须定义构造函数,的时候,派生类必须定义构造函数,且且显式调用显式调用派生类中构造函数的格式:派生类中构造函数的格式:派生类构造函数名(参数表派生类构造函数名(参数表):基类构造函数名(参数表)基类构造函数名(参数表) /对新成员的构造对新成员的构造 显式调用显式调用基类的构造函数基类的构造函数去掉则为去掉则为隐式调用隐式调用必须显式或隐式调用必须显式或隐式调用6.2、派生类的构造函数和析构函数派生类的构造函数和析构函数举例举例/point.h文件,文件,Poi

19、nt类的声明类的声明#include #ifndef POINT_H#define POINT_Hclass Point /声明声明Point类类 public:Point( int = 0,int = 0); /Point的构造函数的构造函数Point(); /Point的析构函数的析构函数 protected:int x,y;6.2、派生类的构造函数和析构函数派生类的构造函数和析构函数/定义定义Point类的成员函数类的成员函数Point:Point(int a,int b) /定义定义Point类的构造函数类的构造函数x=a;y=b;coutPoint constructor:x,yen

20、dl;Point:Point() /定义定义Point类的析构函数类的析构函数coutPoint destructor:x,yendl;#endif6.2、派生类的构造函数和析构函数派生类的构造函数和析构函数/circle.h文件,文件,Circle类的声明类的声明#ifndef CIRCLE_H#define CIRCLE_H#include “point.h”class Circle:public Point /声明声明Circle类继承自类类继承自类Point public:Circle(double r=0.0,int x=0,int y=0); /Circle类类 /的构造函数的构造

21、函数Circle(); /Circle类的析构函数类的析构函数 private:double radius;6.2、派生类的构造函数和析构函数派生类的构造函数和析构函数/ 定义定义Circle类的成员函数类的成员函数Circle:Circle(double r,int a,int b):Point(a,b)radius = r;coutCircle constructor:radius is radiusx,yendl;Circle:Circle()coutCircle destructor:radius is radiusx,yendl;#endif 6.2、派生类的构造函数和析构函数派生类

22、的构造函数和析构函数/try.cpp文件文件#include “point.h”#include “circle.h”int main()/演示演示Point类构造函数和类构造函数和析构函数的调用析构函数的调用 Point p(11,22); coutendl;Circle circle1(4.5,72,29);coutendl;Circle circle2(10,5,5);coutendl;return 0;Circle destructor:radius is 10 5,5Point destructor:5,5Circle destructor:radius is 4.5 72,29Po

23、int destructor:72,29程序输出结果程序输出结果:Point Constructor:11,22Point destructor:11,22Point Constructor:72,29Circle constructor:radius is 4.5 72,29Point Constructor:5,5Circle constructor:radius is 10 5,56.2、派生类的构造函数和析构函数派生类的构造函数和析构函数#define POINT_H class Point /声明声明Point类类#define CIRCLE_H#define POINT_H cla

24、ss Point /声明声明Point类类class Circle:public Point /声明声明Circle类继承自类类继承自类Pointint main()6.2、派生类的构造函数和析构函数派生类的构造函数和析构函数该例中定义了该例中定义了Point类和它的公有派生类类和它的公有派生类Circle。(1)在定义在定义Circle类的成员函数时,显示调用类的成员函数时,显示调用Point类类的构造函数来对的构造函数来对Cirle类中的基类成员初始化类中的基类成员初始化。(2)在在main()函数中,先实例化了一个函数中,先实例化了一个Point对象,对象,由于该对象在进入其作用域后又立

25、即退出其作用域,由于该对象在进入其作用域后又立即退出其作用域,因此调用了因此调用了Point的构造函数和析构函数的构造函数和析构函数(3)实例化实例化Cirlcle的对象的对象circle1时,时,首先调用了首先调用了Point的构造函数,然后再调用的构造函数,然后再调用Circle的构造函数。接的构造函数。接着,程序以同样的顺序实例化了着,程序以同样的顺序实例化了circle2对象。对象。6.2、派生类的构造函数和析构函数派生类的构造函数和析构函数在在main函数结束时,程序为函数结束时,程序为circle1和和circle2调用析构函数,因为析构函数的调用顺序和构造调用析构函数,因为析构函

26、数的调用顺序和构造函数相反,因此先为对象函数相反,因此先为对象circle2调用析构函数,调用析构函数,调用顺序是先调用类调用顺序是先调用类Circle的析构函数的析构函数,再调用类再调用类Point的析构函数。为对象的析构函数。为对象circle2调用析构函数完调用析构函数完成后,再以相同的顺序为对象成后,再以相同的顺序为对象circle1调用析构函调用析构函数。数。6.3、多重继承、多重继承1、定义、语法、定义、语法定义定义:多重继承是派生类有多个基类的派生方法:多重继承是派生类有多个基类的派生方法语法语法:class 派生类名派生类名:派生方式派生方式1 基类名基类名1, , 派生方式派

27、生方式n 基类名基类名n /派生类新增的数据成员和成员函数派生类新增的数据成员和成员函数;派生方式派生方式可以各不相同可以各不相同6.3、多重继承、多重继承2、访问权限、构造和析构次序、访问权限、构造和析构次序在多重继承中,公有派生和私有派生对于基类成员在派在多重继承中,公有派生和私有派生对于基类成员在派生类中的可访问性和单继承的生类中的可访问性和单继承的规则相同规则相同基类基类基类基类派生类派生类基类基类成员成员基类基类成员成员新成员新成员派生派生派生派生6.3、多重继承、多重继承构造和析构次序:构造和析构次序:在多重继承中,多重继承构造函数的执行顺序与单继承在多重继承中,多重继承构造函数的

28、执行顺序与单继承构造函数的执行顺序相同,遵循先执行构造函数的执行顺序相同,遵循先执行基类的构造函数基类的构造函数,再执行再执行对象成员的构造函数对象成员的构造函数,最后执行,最后执行派生类的构造函派生类的构造函数数的原则。的原则。6.2、派生类的构造函数和析构函数派生类的构造函数和析构函数举例:举例:#include class X /声明基类声明基类int a;public:X(int sa) a=sa;int getX() return a;class Y /声明另外的基类声明另外的基类int b;public:Y(int sb) b=sb;int getY() return b;6.2、

29、派生类的构造函数和析构函数派生类的构造函数和析构函数class Z : public X, private Y /声明派生类,多重继承声明派生类,多重继承int c;public:Z(int sa,int sb,int sc):X(sa),Y(sb) /Z的的构造函数构造函数 c=sc; /并并调用基类构造函数调用基类构造函数int getZ() return c;int getY() return Y:getY(); /重新定义继承来的函数重新定义继承来的函数;main() /主函数主函数Z obj(2,4,6); /声明对象声明对象objint ma=obj.getX(); /调用基类调用

30、基类X的方法的方法cout“a=”maendl;cout“b=”obj.getY()endl; return 0;return c+1;6.3、多重继承、多重继承XYZa getX派生派生派生派生b getYc getZ6.3、多重继承、多重继承3、继承的模糊性(继承歧义性)继承的模糊性(继承歧义性) #include class Veichle /定义交通工具类定义交通工具类 public:Veichle(double w = 0)cout“Veichle constructor”endl; weight = w; void setWeight(double w) cout“set weig

31、ht:”endl; weight = w; protected:double weight; ;6.2、派生类的构造函数和析构函数派生类的构造函数和析构函数class Veichle_Road: public Veichle /定义陆地交通工具类定义陆地交通工具类public:Veichle_Road(double weitht=0,int s=0): Veichle(weight)cout Veichle_Road constructorendl; speed = s; protected:int speed;6.2、派生类的构造函数和析构函数派生类的构造函数和析构函数class Veich

32、le_Water:public Veichle /定义水上交通工具类定义水上交通工具类public:Veichle_Water(double weight=0,float t=0): Veichle(weight) cout Veichle_Water constructorendl;tonnage = t; protected:float tonnage;6.2、派生类的构造函数和析构函数派生类的构造函数和析构函数class Amphicar : public Veichle_Road, public Veichle_Waterpublic:/多重继承,调用基类构造函数多重继承,调用基类构造

33、函数 Amphicar(double w, int s, float t) : Veichle_Road(w,s), Veichle_Water(w,t) /正确正确, 分别初始化两个分别初始化两个wcout “ Amphicar constructor”endl; void display( ) /显示显示Amphicar成员成员cout“ weight: ” weight“ ,” endl; /错误错误,因为多继承带来的歧义性因为多继承带来的歧义性 cout speed:speedendl;cout tonnage: tonnageendl; ;显示哪个显示哪个w?6.2、派生类的构造函数

34、和析构函数派生类的构造函数和析构函数void main( )Amphicar a(4.0,200,1.50f); /正确正确 a.setWeight(3.5); /错误错误, 因为多继承带来的歧义性因为多继承带来的歧义性 a.display( );原因原因: a从从Veichle_Road和和Veichle_Water继承了继承了w、setWeight()的()的两个两个拷贝拷贝解决解决: 采用虚拟继承!采用虚拟继承!此外此外: 从不同类继承同名成员,也会出现从不同类继承同名成员,也会出现歧义性歧义性6.3、多重继承、多重继承4、虚拟继承虚拟继承目的目的:如果要使公共基类只产生一个拷贝,则应当

35、把:如果要使公共基类只产生一个拷贝,则应当把这个基类声明为虚基类。这个基类声明为虚基类。 即:要求从基类派生新类时,使用即:要求从基类派生新类时,使用关键字关键字virtual将基类声明为虚基类。将基类声明为虚基类。语法语法:class 派生类名派生类名:virtual 派生派生方式方式 基类名基类名;虚基类虚基类6.3、多重继承、多重继承修改上例:修改上例:#include class Veichle /定义交通工具类定义交通工具类public:Veichle(double w = 0)coutVeichle constructorendl; weight = w; void setWeig

36、ht(double w) coutset weight=wendl;weight = w; protected:double weight; ;6.3、多重继承、多重继承class Veichle_Road: virtual public Veichle /虚继承虚继承public:Veichle_Road(double weitht=0,int s=0): Veichle(weight) cout Veichle_Road constructorendl; speed = s; protected:int speed;6.3、多重继承、多重继承class Veichle_Water:virt

37、ual public Veichle /水上交通工具水上交通工具,这里是这里是 /虚拟继承虚拟继承 public:Veichle_Water(double weight=0,float t=0): Veichle(weight) cout Veichle_Water constructorendl;tonnage = t; protected:float tonnage;6.3、多重继承、多重继承class Amphicar :public Veichle_Road, public Veichle_Water /多继承多继承 public: Amphicar(double w, int s,

38、float t):Veichle(w), Veichle_Road(w,s), Veichle_Water(w,t) cout Amphicar constructorendl; void display( ) /显示显示Amphicar的的Weight成员成员coutAmphicar object contains: endl;cout weight: weightendl;cout speed:speedendl; cout tonnage: tonnageendl; ;6.3、多重继承、多重继承void main( )Amphicar amp(4.0,200,1.50f);amp.set

39、Weight(2.0); /调用调用Veichel的的setWeight成员成员amp.display();6.3、多重继承、多重继承程序输出结果程序输出结果:Veichle constructorVeichle_Road constructorVeichle_Water constructor(此处不调用此处不调用Veichle构造该函数构造该函数) Amphicar constructorset weight=2Amphicar object contains: weight: 2speed:200tonnage:1.56.3、多重继承、多重继承分析:分析:从类从类Veichle派生出类派

40、生出类Veichle_Road和类和类Veichle_Water时,使用了关键字时,使用了关键字virtual实现虚拟实现虚拟继承继承。则对于虚基类则对于虚基类Veichle ,编译器编译器遇到多重继承时会遇到多重继承时会自自动动加上一个拷贝,当加上一个拷贝,当再次请求再次请求一个一个Veichle拷贝时就拷贝时就会会被忽略被忽略,保证继承成员的唯一性。,保证继承成员的唯一性。6.3、多重继承、多重继承类类Amphicar只有一个只有一个Veichle类的拷贝,从类的拷贝,从而既可以消除歧义性,而既可以消除歧义性,又可以正确的描述类又可以正确的描述类层次结构层次结构一个一个Amphicar对象

41、在内存中的布局如下图对象在内存中的布局如下图: 不能将不能将virtual写在写在Amphicar 的定义处的定义处6.3、多重继承、多重继承weightVeichlesetWeightweightVeichlesetWeightspeedweightsetWeighttonnageweightsetWeightspeedweightsetWeighttonnageweightsetWeightspeedweightsetWeightVeichle_RoadtonnageweightsetWeightVeichle_WaterspeedweightsetWeighttonnageweights

42、etWeightAmphicar6.3、多重继承、多重继承使用使用虚拟继承机制的注意事项:虚拟继承机制的注意事项:1、如果在虚基类中定义了带参数的构造函数,在整个继承结如果在虚基类中定义了带参数的构造函数,在整个继承结构中,所有的直接或间接派生类中都必须在构造函数中使用构中,所有的直接或间接派生类中都必须在构造函数中使用成员初始化列表的方式调用虚基类的构造函数,初始化虚基成员初始化列表的方式调用虚基类的构造函数,初始化虚基类中的成员类中的成员2、如果在同一个继承层次中同时包含虚基类和非虚基类,如果在同一个继承层次中同时包含虚基类和非虚基类, C+编译器先调用虚基类的构造函数,再调用非虚基类的构

43、编译器先调用虚基类的构造函数,再调用非虚基类的构造函数造函数3、如果虚基类是由非虚基类派生而来,同样遵守先调用基如果虚基类是由非虚基类派生而来,同样遵守先调用基类构造函数再调用派生类构造函数的规则类构造函数再调用派生类构造函数的规则6.3、多重继承、多重继承慎用多重慎用多重继承:继承:尽管多重机制在一定程度上强化了对现实世界中尽管多重机制在一定程度上强化了对现实世界中事物的描述,但是在实际应用中并不建议使用多事物的描述,但是在实际应用中并不建议使用多重继承,主要是因为编译器的问题,还有多重继重继承,主要是因为编译器的问题,还有多重继承机制会带来二义性问题。单继承对描述事物已承机制会带来二义性问

44、题。单继承对描述事物已经提供了足够强大的功能,不一定非要使用多继经提供了足够强大的功能,不一定非要使用多继承不可承不可6.3、多重继承、多重继承引入引入虚拟继承后,多重继承中虚拟继承后,多重继承中构造函数和析构构造函数和析构函数的执行函数的执行顺序顺序 (对前面内容的扩展)(对前面内容的扩展)1、任何、任何虚拟继承基类虚拟继承基类的构造函数按照它们被继承的顺序构造的构造函数按照它们被继承的顺序构造2、任何任何非虚拟基类非虚拟基类的构造函数按照它们被继承的顺序构造的构造函数按照它们被继承的顺序构造3、派生类自己的构造函数派生类自己的构造函数析构函数的执行顺序与构造函数执行的顺序相反析构函数的执行

45、顺序与构造函数执行的顺序相反6.3、多重继承、多重继承/检验多重继承构造顺序检验多重继承构造顺序#include class Base1public:Base1( )coutBase1 construcotrendl;Base1( ) coutBase1deconstrucotrendl;class Base2public:Base2( ) coutBase2 construcotrendl; Base2() coutBase2 deconstrucotrendl;6.3、多重继承、多重继承class Base3public:Base3( ) coutBase3 construcotrendl

46、; Base3( ) coutBase3 deconstrucotrendl; ;class Base4public:Base4( ) coutBase4 construcotrendl;Base4( ) coutBase4 deconstrucotrendl;6.3、多重继承、多重继承class Member1public:Member1( ) coutMember1 construcotrendl; Member1( ) coutMember1 deconstrucotrendl;class Member2public:Member2( ) coutMember2 construcotre

47、ndl; Member2( ) coutMember2 deconstrucotrendl;6.3、多重继承、多重继承class Derived: public Base1,virtual public Base2, public Base3,virtual public Base4 public:Derived( ):Base1( ),Base2( ),Base3( ),Base4( ), mem1 ( ), mem2 ( ) cout Derived constructorendl; Derived( ) cout Derived constructorendl; ;private: Me

48、mber1 mem1; Member2 mem2;6.3、多重继承、多重继承int main( ) Derived obj;coutconstructor finish!endl;return 0;程序运行结果为程序运行结果为:Base2 construcotrBase4 construcotrBase1 construcotrBase3 construcotrMember1 construcotrMember2 construcotrDerived constructorconstructor finish! Derived deconstructorMember2 deconstrucot

49、rMember1 deconstrucotrBase3 deconstrucotrBase1 deconstrucotrBase4 deconstrucotrBase2 deconstrucotr 6.3、多重继承、多重继承输出结果表明:输出结果表明:Derived的虚基类的虚基类Base2和和Base4首先被构造,首先被构造,非虚基类非虚基类Base1和和Base3随后被构造,与它们在随后被构造,与它们在Derived的构造函数中出现的次序无关。的构造函数中出现的次序无关。然后然后Derived的成员对象的成员对象Mem1和和Mem2按照在按照在Derived中声明的顺序构造,中声明的顺序构

50、造,最后执行最后执行Derived的构造函数,构造的构造函数,构造Derived对象。对象。析构函数的执行顺序与构造函数相反析构函数的执行顺序与构造函数相反本章小结本章小结1、本章介绍了、本章介绍了C+中关于继承机制的相关知识中关于继承机制的相关知识,使使用继承机制可以简化对事物的描述用继承机制可以简化对事物的描述,同时更好的实现同时更好的实现软件复用。继承分为单继承和多重继承软件复用。继承分为单继承和多重继承,我们别按照我们别按照如何声明派生类如何声明派生类、 继承的访问控制继承的访问控制、 派生类的构造派生类的构造和析构和析构对两种继承机制进行了详细的介绍对两种继承机制进行了详细的介绍。2

51、、关于多继承,我们重点介绍了、关于多继承,我们重点介绍了多重继承的模糊性多重继承的模糊性,并引入了并引入了虚拟继承虚拟继承。在语言中实现多继承并不容易,。在语言中实现多继承并不容易,主要是编译程序的问题和多重继承可能会产生二义性,主要是编译程序的问题和多重继承可能会产生二义性,在实际开发中,应避免使用多重继承。在实际开发中,应避免使用多重继承。综合训练综合训练1题目题目:编写程序列出某读者的借书情况:编写程序列出某读者的借书情况: 假设图书馆的图书包含假设图书馆的图书包含书名、编号、作者属性书名、编号、作者属性。读者包含读者包含姓名姓名和和借书证编号属性借书证编号属性,每位读者最多可借,每位读者最多可借5本书,本书,综合训练综合训练1分析分析show()namenoshowbook()bookauthornamenoshowreader()reader对象数组:存放借书对象数组:存放借书showbook() show() 显示作者显示作者showreader() show() 显示借书显示借书 namenoshow()show()综合训练综合训练1#include #include class object char name2

温馨提示

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

评论

0/150

提交评论