C++程序设计 第11章 继承和派生_第1页
C++程序设计 第11章 继承和派生_第2页
C++程序设计 第11章 继承和派生_第3页
C++程序设计 第11章 继承和派生_第4页
C++程序设计 第11章 继承和派生_第5页
已阅读5页,还剩94页未读 继续免费阅读

下载本文档

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

文档简介

1、第十一章第十一章 继承和派生继承和派生本章主要内容n类之间的关系类之间的关系n基类和派生类基类和派生类n基类的初始化基类的初始化n继承的应用实例继承的应用实例n多继承多继承n继承时的构造函数继承时的构造函数或者: class 类名 private: 私有的数据和成员函数; public: 公有的数据和成员函数; 相关知识说明nclass是定义类的关键字。n是一个标识符,用于唯一标识一个类。n类的说明部分,说明该类的所有成员。n类的成员包括数据成员和成员函数两部分。n类的成员从访问权限上分有以下三类:n公有的(public)n私有的(private)n保护的(protected)n其中默认为pr

2、ivate权限。n公有的成员(public)n可以被程序中的任何代码访问;n私有的成员(private)n只能被类本身的成员函数及友元类的成员函数访问,其他类的成员函数,包括其派生类的成员函数都不能访问它们;n保护的成员(protected)n与私有成员类似,只是除了类本身的成员函数和说明为友元类的成员函数可以访问保护成员外,该类的派生类的成员也可以访问。11.1 11.1 类之间的关系类之间的关系 不具有对称性不具有对称性 不是所有植物都属于蕨类传递性传递性 高等植物、蕨类植物、芒萁都是植物,具有植物的共同特征 植物植物 低等植物低等植物高等植物高等植物藻类藻类菌类菌类地衣类地衣类苔藓类苔藓

3、类蕨类蕨类裸子类裸子类被子类被子类地钱地钱小金发草小金发草毛蕨毛蕨芒萁芒萁杉木杉木柏木柏木荔枝荔枝橘子橘子1.1.继承是指一个类从另一个或另一些类获得了一些基本性质,并在此基础上增加了自身的一些特殊性质。2.2.继承是建立在类的一般化结构(通用特殊结构)基础上的。也即特殊类继承了一般类的性质。一般类基类,或超类。特殊类派生类,或子类。派生类是基类的具体化,而基类则是派生类的抽象11.1 11.1 类之间的继承关系类之间的继承关系 3. 3. 继承的关键成分(1)实体所具有的共性(2)实体间的区别,也即实体自身所具有的个性。 例如,正方形具有与四边形相同的性质。 例如,正方形的四条边必须等长。(

4、3)实体之间存在一般特殊关系,从而可以建立层次结构。11.1 11.1 类之间的关系类之间的关系 继承与派生问题举例工具车轿车面包车小汽车卡车旅行车汽车汽车交通工具交通工具11.1 11.1 类之间的关系类之间的关系 继承与派生问题举例猴猴 子子狮 子虎猎 豹猫猫鸟鸟动动 物物猫科猫科11.1 11.1 类之间的关系类之间的关系 继承与派生问题举例圆圆矩形矩形几何形状几何形状11.1 11.1 类之间的关系类之间的关系 11.1 11.1 类之间的关系类之间的关系 继承继承 是类之间定义的一种重要关系 一个 B 类继承A类,或称从类 A 派生类 B 类 A 称为基类(父类),类 B 称为派生类

5、(子类)AB1B2C1C2C3B1,B2 的基类的基类A 的派生类的派生类C1,C2,C3 的基类的基类A 的派生类(单继承)的派生类(单继承)C3的基类的基类B1,B2 的派生类(多继承)的派生类(多继承)B1 的派生类的派生类类继承关系的语法形式类继承关系的语法形式class 派生类名 : 基类名表 数据成员和成员函数声明 ;11.2 11.2 基类和派生类基类和派生类class student1:public student void display_1() cout“age:”ageendl; cout“address:” address endl; Private: int age;

6、 string addr; 类继承关系的语法形式类继承关系的语法形式class 派生类名 : 基类名表基类名表 数据成员和成员函数声明 ;11.2 11.2 基类和派生类基类和派生类基类名表基类名表 构成访问控制 基类名1, 访问控制 基类名2 , , 访问控制 基类名n类继承关系的语法形式类继承关系的语法形式class 派生类名 : 基类名表 数据成员和成员函数声明 ;11.2 11.2 基类和派生类基类和派生类基类名表 构成访问控制访问控制 基类名1, 访问控制访问控制 基类名2 , , 访问控制访问控制 基类名n访问控制访问控制 表示派生类对基类的继承方式,使用关键字: 公有继承 私有继

7、承 保护继承派生类的构成派生类的构成 基类基类 派生类派生类Student类int num;char name10;char sex;void display();数数据据成成员员成员成员函数函数Student1类int num;char name10;char sex;void display();int age;char addr30;void display();新新增增继承继承11.2 11.2 基类和派生类基类和派生类派生类对基类成员的使用,与继承访问控制和基类中成员性质有关公有继承公有继承基类的公有成员派生类的公有成员 基类的保护成员派生类的保护成员私有继承私有继承 基类的公有成员

8、和保护成员派生类的私有成员保护继承保护继承 基类的公有成员和保护成员派生类的保护成员不论种方式继承基类,派生类都不能直接使用基类的私有成员 7.2.1 访问控制11.2.1 11.2.1 访问控制访问控制继承方式继承方式基类成员的访基类成员的访问权限问权限派生类对基类成员的访问派生类对基类成员的访问权限权限publicpublic公有继承公有继承publicpublicprivateprivateprotectedprotectedpublicpublic不可见不可见protectedprotectedprivateprivate私有继承私有继承publicpublicprivatepriva

9、teprotectedprotectedprivateprivate不可见不可见privateprivateprotectedprotected保护继承保护继承publicpublicprivateprivateprotectedprotectedprotectedprotected不可见不可见protectedprotected7.2.1 访问控制1.1.公有继承公有继承public 成员成员 public 成员成员protected 成员成员 protected 成员成员private 成员成员public 成员成员protected 成员成员private 成员成员基类基类派生类派生类#

10、includeclass A public : void get_XY() cout x y ; void put_XY() cout x = x , y = y n ; protected: int x, y ;class B : public A public : int get_S() return s ; ; void make_S() s = x * y ; ; / 使用基类数据成员使用基类数据成员x,y protected: int s;class C : public B public : void get_H() cout h ; int get_V() return v ;

11、void make_V() make_S(); v = get_S() * h ; / 使用基类成员函数使用基类成员函数 protected: int h, v;例例 公有继承的测试公有继承的测试 7.2.1 7.2.1 访问控制访问控制class Aclass C : public Bclass B : public Avoid main() A objA ; B objB ; C objC ; cout It is object_A :n ; objA.get_XY() ; objA.put_XY() ; cout It is object_B :n ; objB.get_XY() ; o

12、bjB.make_S() ; cout S = objB.get_S() endl ; cout It is object_C :n ; objC.get_XY() ; objC.get_H(); objC.make_V() ; cout V = objC.get_V() endl ;objA.yobjA.xobjAobjB.sobjB.yobjB.xobjBobjC.hobjC.vobjC.sobjC.yobjC.xobjCx y sh v 7.2.1 7.2.1 访问控制访问控制例例 公有继承的测试公有继承的测试 7.2.1 访问控制public 成员成员protected 成员成员pri

13、vate 成员成员public 成员成员protected 成员成员private 成员成员基类基类派生类派生类private 成员成员private 成员成员2.2.私有继承私有继承#includeclass A public : void get_XY() cout x y ; void put_XY() cout x = x , y = y n ; protected: int x, y ;class B : private A public : int get_S() return s ; void make_S() get_XY(); s = x * y ; private: int

14、 s ;void main() B objB ; cout It is object_B :n ; objB.make_S() ; cout S = objB.get_S() endl ; 例例 私有继承的测试私有继承的测试 class B : private Aclass A objB.sobjB.yobjB.xobjBprivate成员成员7.2.1 7.2.1 访问控制访问控制#includeclass A public : void get_XY() cout x y ; void put_XY() cout x = x , y = y n ; protected: int x, y

15、;class B : private A public : int get_S() return s ; void make_S() get_XY(); s = x * y ; private: int s ;void main() B objB ; cout It is object_B :n ; objB.make_S() ; cout S = objB.get_S() endl ; class B : private Aclass A objB.sobjB.yobjB.xobjBprivate成员成员7.2.1 7.2.1 访问控制访问控制例例 私有继承的测试私有继承的测试 #inclu

16、declass A public: A() x=1; int out() return x ; void addX() x+; private: int x ; ;class B : public A public: B() y=1; int out() return y ; void addY() y+; private:int y ; ;void main() A a ; B b ; b.addX() ; b.addY() ; cout a.x= a.out() endl ; cout b.x= b.A:out() endl ; cout b.y= b.out() endl ;例例 私有数

17、据成员的测试私有数据成员的测试 class B : public Aclass A 基类的私有数据成员基类的私有数据成员不能在派生类中直接访问不能在派生类中直接访问但派生类对象建立私有数据空间但派生类对象建立私有数据空间 b.xa.xb.y7.2.1 7.2.1 访问控制访问控制#includeclass A public: A() x=1; int out() return x ; void addX() x+; private: int x ; ;class B : public A public: B() y=1; int out() return y ; void addY() y+;

18、 private:int y ; ;void main() A a ; cout a.x= a.out() endl ; B b ; b.addX() ; b.addY() ; cout b.x= b.A:out() endl ; cout b.y= b.out() endl ;class B : public Aclass A b.xa.xb.y7.2.1 7.2.1 访问控制访问控制例例 私有数据成员的测试私有数据成员的测试7.2.1 访问控制public 成员成员protected 成员成员private 成员成员public 成员成员protected 成员成员private 成员成员

19、基类基类派生类派生类protected 成员成员protected 成员成员3.3.保护继承保护继承 派生类定义了与基类同名的成员,在派生类中访问同名成员派生类定义了与基类同名的成员,在派生类中访问同名成员 时屏蔽了基类的同名成员时屏蔽了基类的同名成员 在在派生类中使用基类的同名成员,显式地使用类名限定符:派生类中使用基类的同名成员,显式地使用类名限定符:类名类名 : 成员成员 7.2.2 重名成员11.2.2 11.2.2 重名成员重名成员例:例:class base public : int a , b ; ;class derived : public base public : int

20、 b , c ; ;void f () derived d ; d . a = 1 ; d . base : b = 2 ; d . b = 3 ; d . c = 4 ;7.2.2 重名成员base a b 4321derived derived a b 基类成员的作用域延伸到所有派生类基类成员的作用域延伸到所有派生类派生类的重名成员屏蔽基类的同名成员派生类的重名成员屏蔽基类的同名成员1.1.重名数据成员重名数据成员/例例#includeclass A public: int a1, a2 ; A( int i1=0, int i2=0 ) a1 = i1; a2 = i2; void pr

21、int() cout a1= a1 t a2= a2 endl ; ;class B : public A public: int b1, b2 ; B( int j1=1, int j2=1 ) b1 = j1; b2 = j2; void print()/定义同名函数定义同名函数 cout b1= b1 t b2= b2 endl ; void printAB() A:print() ;/派生类对象调用基类版本同名成员函数派生类对象调用基类版本同名成员函数 print() ;/派生类对象调用自身的成员函数派生类对象调用自身的成员函数 ;void main() B b ; b.A:print

22、();b.printAB(); 7.2.2 重名成员2.2.重名成员函数重名成员函数类型兼容规则n一个公有派生类的对象在使用上可以被当作基类的对象,反之则禁止。具体表现在:n派生类的对象可以被赋值给基类对象。n派生类的对象可以初始化基类的引用。n指向基类的指针也可以指向派生类。n通过基类对象名、指针只能使用从基类继承的成员例 类型兼容规则举例#include using namecpace std;class B0/基类B0声明 public:void display()coutB0:display()endl;/公有成员函数;class B1: public B0 public:void d

23、isplay()coutB1:display()endl;class D1: public B1public:void display()coutD1:display()display();/对象指针-成员名 int main() /主函数 B0 b0;/声明B0类对象B1 b1;/声明B1类对象D1 d1;/声明D1类对象B0 *p;/声明B0类指针p=&b0; /B0类指针指向B0类对象fun(p);p=&b1; /B0类指针指向B1类对象fun(p);p=&d1; /B0类指针指向D1类对象fun(p);运行结果:B0:display()B0:displaydis

24、play()B0:display()11.3 11.3 基类的初始化基类的初始化 建立一个类层次后,通常创建某个派生类的对象,包括使用基类的数据和函数 C+提供一种机制,在创建派生类对象时用指定参数调用基类的构造函数来初始化派生类继承基类的数据 派生类构造函数声明为派生类构造函数派生类构造函数 ( 变元表变元表 ) : 基类基类 ( 变元表变元表 ) , 对象成员对象成员1( 变元表变元表 ) 对象成员对象成员n ( 变元表变元表 ) ; 构造函数执行顺序:基类 对象成员 派生类/ 例例 调用构造函数顺序测试,构造函数无参数调用构造函数顺序测试,构造函数无参数#include class Ba

25、se public : Base ( ) cout Base created.n ; ;class D_class : public Base public : D_class ( ) cout D_class created.n ; ;void main ( ) D_class d1 ; 7.3 基类的初始化#include class parent_class int data1 , data2 ; public : parent_class ( int p1 , int p2 ) data1 = p1; data2 = p2; int inc1 () return + data1; in

26、t inc2 () return + data2 ; void display () cout data1= data1 , data2= data2 endl ; ;class derived_class : private parent_class int data3 ; parent_class data4 ; public: derived_class ( int p1 , int p2 , int p3 , int p4 , int p5 ): parent_class ( p1 , p2 ) , data4 ( p3 , p4 ) data3 = p5 ; int inc1 ( )

27、 return parent_class : inc1 ( ) ; int inc3 ( ) return + data3 ; void display ( ) parent_class : display ( ) ; data4.display ( ) ; cout data3= data3 endl ; ;void main ( ) derived_class d1 ( 17 , 18 , 1 , 2 , -5 ) ; d1 . inc1 ( ) ; d1 . display ( ) ; 例例 带参数构造函数调用顺序测试带参数构造函数调用顺序测试7.3 7.3 基类的初始化基类的初始化11

28、.4 11.4 继承的应用实例继承的应用实例PointCircleCylinderclass Point friend ostream &operator (ostream &, const Point &); public: Point( int = 0, int = 0 ) ;/ 带默认参数的构造函数带默认参数的构造函数 void setPoint( int, int ) ;/ 对点坐标数据赋值对点坐标数据赋值 int getX() const return x ; int getY() const return y ; protected: int x, y;/

29、Point类的数据成员类的数据成员;class Circle : public Point friend ostream &operator (ostream &, const Circle &);/ 友员函数友员函数 public: Circle(double r=0.0, int x=0, int y=0);/ 构造函数构造函数 void setRadius(double); /*置半径置半径*/ double getRadius() const; /*返回半径返回半径*/ double area() const;/ 返回面积返回面积 protected: doub

30、le radius;/ 数据成员,半径数据成员,半径;class Cylinder:public Circle friend ostream & operator(ostream &, const Cylinder &); / 友员函数友员函数 public: Cylinder(double h=0.0, double r=0.0, int x=0, int y=0); / 构造函数构造函数 void setHeight(double); /* 置高度值置高度值*/ double getHeight() const; /* 返回高度返回高度值值*/ double are

31、a() const; /* 返回面积返回面积*/ double volume() const; /* 返回体积返回体积*/ protected: double height;/ 数据成员,高度数据成员,高度;7.4 继承的应用实例/ Point 类的成员函数类的成员函数 / 构造函数,调用成员函数对构造函数,调用成员函数对 x,y作初始化作初始化Point:Point ( int a, int b ) setPoint ( a , b ) ; / 对数据成员置值对数据成员置值void Point : setPoint ( int a, int b ) x = a ; y = b ; / 重载插

32、入算符,输出对象数据重载插入算符,输出对象数据ostream &operator ( ostream &output , const Point &p ) output p.x , p.y = 0 ? r : 0 ); / 返回半径值返回半径值double Circle:getRadius() const return radius; / 计算并返回面积值计算并返回面积值double Circle:area() const return 3.14159 * radius * radius ; / 输出圆心坐标和半径值输出圆心坐标和半径值ostream & ope

33、rator ( ostream &output, const Circle &c) output Center = c.x , c.y ; Radius = setiosflags(ios:fixed|ios:showpoint) setprecision(2) = 0 ? h : 0 ); / 返回高度值返回高度值double Cylinder:getHeight() const return height; / 计算并返回圆柱体的表面积计算并返回圆柱体的表面积d o u b l e C y l i n d e r : : a r e a ( ) c o n s t r e

34、t u r n 2*Circle:area()+2*3.14159*radius*height; / 计算并返回圆柱体的体积计算并返回圆柱体的体积double Cylinder:volume() const return Circle:area()*height; / 输出数据成员圆心坐标、半径和高度值输出数据成员圆心坐标、半径和高度值ostream &operator ( ostream &output, const Cylinder &cy ) output Center = cy.x , cy.y ; Radius = setiosflags(ios:fixed|

35、ios:showpoint) setprecision(2) cy.radius ; Height = cy.height endl ; return output; 7.4 7.4 继承的应用实例继承的应用实例#include #include void main() Point p ( 72, 115 ) ;/定义点对象并初始化定义点对象并初始化 cout The initial location of p is p endl ; p.setPoint ( 10, 10 ) ;/置点的新数据值置点的新数据值 cout nThe new location of p is p endl ;/输

36、出数据输出数据 Circle c ( 2.5, 37, 43 ) ;/定义圆对象并初始化定义圆对象并初始化 coutnThe initial location and radius of c arencnArea = c.area()n ; /置圆的新数据值置圆的新数据值 c.setRadius ( 4.25 ) ; c.setPoint ( 2, 2 ) ; /输出圆心坐标和圆面积输出圆心坐标和圆面积 coutnThe new location and radius of c arencnArea = c.area() n ; Cylinder cyl ( 5.7, 2.5, 12, 23

37、) ;/定义圆柱体对象并初始化定义圆柱体对象并初始化 /输出圆柱体各数据和表面积,体积输出圆柱体各数据和表面积,体积 cout nThe initial location, radius ang height of cyl aren cyl Area = cyl.area() nVolume = cyl.volume() n; /置圆柱体的新数据值置圆柱体的新数据值 cyl.setHeight ( 10 ) ; cyl.setRadius ( 4.25 ) ; cyl.setPoint ( 2, 2 ) ; cout nThe new location, radius ang height o

38、f cyl aren cyl Area = cyl.area() nVolume = cyl.volume() n ; 7.4 继承的应用实例TaskDisplayedSatelliteTaskSatellite 一个类有多个直接基类的继承关系称为一个类有多个直接基类的继承关系称为多继承多继承 多继承声明语法多继承声明语法class 派生类名派生类名 : 访问控制访问控制 基类名基类名1 , 访问控制访问控制 基类名基类名2 , , 访问控制访问控制 基类名基类名n 数据成员和成员函数声明数据成员和成员函数声明 ;7.5 多继承class C : public A ,public Bclass

39、 Aclass B 类 C 可以根据访问控制同时继承类 A 和类 B 的成员,并添加 自己的成员7.5 多继承 多个基类的派生类构造函数可以用初始式调用基类构造函数初始化多个基类的派生类构造函数可以用初始式调用基类构造函数初始化数据成员数据成员执行顺序与单继承构造函数情况类似。多个直接基类构造函数执行执行顺序与单继承构造函数情况类似。多个直接基类构造函数执行顺序取决于定义派生类时指定的各个继承基类的顺序。顺序取决于定义派生类时指定的各个继承基类的顺序。 一个派生类对象拥有多个直接或间接基类的成员。不同名成员访问一个派生类对象拥有多个直接或间接基类的成员。不同名成员访问不会出现二义性。如果不同的

40、基类有同名成员,派生类对象访问时应不会出现二义性。如果不同的基类有同名成员,派生类对象访问时应该加以识别。该加以识别。 11.5.1 11.5.1 多继承的派生类构造和访问多继承的派生类构造和访问7.5.1 多继承的派生类构造和访问class Derived : public Base1, public Base2 friend ostream &operator ( ostream &, const Derived & ) ; public : Derived ( int, char, double ) ; double getReal() const ; priva

41、te : double real ;class Base1 public: Base1(int x) value = x ; int getData() const return value ; protected: int value;class Base2 public: Base2(char c) letter=c; char getData() const return letter; protected: char letter;多继承的简单应用多继承的简单应用 7.5.1 多继承的派生类构造和访问多继承的派生类构造和访问多继承的简单应用多继承的简单应用 class Base1 pu

42、blic: Base1(int x) value = x ; int getData() const return value ; protected: int value;class Base2 public: Base2(char c) letter=c; char getData() const return letter; protected: char letter;class Derived : public Base1, public Base2 friend ostream &operator ( ostream &, const Derived & )

43、 ; public : Derived ( int, char, double ) ; double getReal() const ; private : double real ;void main() Base1 b1 ( 10 ) ; Base2 b2 ( k ) ; Derived d ( 5, A, 2.5 ) ; : return ;K2.5A510value letter realBasc1 b1Basc2 b2Derived d7.5.1 多继承的派生类构造和访问多继承的派生类构造和访问n基类的构造函数不被继承,派生类中需要声明自基类的构造函数不被继承,派生类中需要声明自己的

44、构造函数。己的构造函数。n声明构造函数时,只需要对本类中新增成员进行声明构造函数时,只需要对本类中新增成员进行初始化,对继承来的基类成员的初始化,自动调初始化,对继承来的基类成员的初始化,自动调用基类构造函数完成。用基类构造函数完成。n派生类的构造函数需要给基类的构造函数传递参派生类的构造函数需要给基类的构造函数传递参数数派生类名派生类名:派生类名派生类名(基类所需的形参,本类成员所需的形参基类所需的形参,本类成员所需的形参):基类名基类名(参数表参数表) 本类成员初始化赋值语句;本类成员初始化赋值语句;11.6.1 11.6.1 单一继承时的构造函数单一继承时的构造函数举例举例#includ

45、eusing namespace std;class B public: B(); B(int i); B(); void Print() const; private: int b;11.6.1 11.6.1 单一继承时的构造函数单一继承时的构造函数B:B() b=0;coutBs default constructor called.endl;B:B(int i) b=i; coutBs constructor called. endl;B:B() coutBs destructor called.endl; void B:Print() const coutbendl; 54class

46、C:public B public: C(); C(int i,int j); C(); void Print() const;private: int c;55C:C() c=0;coutCs default constructor called.endl;C:C(int i,int j):B(i) c=j;coutCs constructor called.endl;C:C() coutCs destructor called.endl; void C:Print() const B:Print(); coutcendl; int main() C obj(5,6); obj.Print(

47、); 56派生类名派生类名:派生类名派生类名(基类基类1形参,基类形参,基类2形参,形参,.基类基类n形参,本类形形参,本类形参参):基类名基类名1(参数参数), 基类名基类名2(参数参数), .基类名基类名n(参数参数) 本类成员初始化赋值语句;本类成员初始化赋值语句;11.6.2 11.6.2 多继承时的构造函数多继承时的构造函数n当基类中声明有默认形式的构造函数或未声明构造函数时,派当基类中声明有默认形式的构造函数或未声明构造函数时,派生类构造函数可以不向基类构造函数传递参数。生类构造函数可以不向基类构造函数传递参数。n若基类中未声明构造函数,派生类中也可以不声明,全采用默若基类中未声明

48、构造函数,派生类中也可以不声明,全采用默认形式构造函数。认形式构造函数。n当基类声明有带形参的构造函数时,派生类也应声明带形参的当基类声明有带形参的构造函数时,派生类也应声明带形参的构造函数,并将参数传递给基类构造函数。构造函数,并将参数传递给基类构造函数。11.6.2 11.6.2 派生类与基类的构造函数派生类与基类的构造函数 派生类名派生类名:派生类名派生类名(基类基类1形参,基类形参,基类2形参,形参,.基类基类n形参,本形参,本类形参类形参):基类名基类名1(参数参数), 基类名基类名2(参数参数), .基类名基类名n(参数参数),对象数,对象数据成员的初始化据成员的初始化 本类成员初

49、始化赋值语句;本类成员初始化赋值语句;11.6.3 11.6.3 多继承且有内嵌对象时的构造函数多继承且有内嵌对象时的构造函数1 调用基类构造函数,调用顺序按照它们被继承时声明的顺序调用基类构造函数,调用顺序按照它们被继承时声明的顺序(从左向右)。(从左向右)。2 调用成员对象的构造函数,调用顺序按照它们在类中声明的调用成员对象的构造函数,调用顺序按照它们在类中声明的顺序。顺序。3 派生类的构造函数体中的内容。派生类的构造函数体中的内容。11.7 11.7 构造函数的调用顺序构造函数的调用顺序拷贝构造函数拷贝构造函数若建立派生类对象时调用默认拷贝构造函数,则编译器将自动调用若建立派生类对象时调

50、用默认拷贝构造函数,则编译器将自动调用基类的默认拷贝构造函数。基类的默认拷贝构造函数。若编写派生类的拷贝构造函数,则需要为基类相应的拷贝构造函数若编写派生类的拷贝构造函数,则需要为基类相应的拷贝构造函数传递参数。例如传递参数。例如:C:C(C &c1):B(c1)例例 派生类构造函数举例派生类构造函数举例#include using namespace std;class B1/基类基类B1,构造函数有参数,构造函数有参数public:B1(int i) coutconstructing B1 iendl;class B2/基类基类B2,构造函数有参数,构造函数有参数public:B2

51、(int j) coutconstructing B2 jendl;class B3/基类基类B3,构造函数无参数,构造函数无参数public:B3()coutconstructing B3 *endl;class C: public B2, public B1, public B3 public:/派生类的公有成员派生类的公有成员C(int a, int b, int c, int d): B1(a),memberB2(d),memberB1(c),B2(b) private:/派生类的私有对象成员派生类的私有对象成员B1 memberB1;B2 memberB2;B3 memberB3;i

52、nt main() C obj(1,2,3,4); 运行结果:constructing B2 2constructing B1 1constructing B3 *constructing B1 3constructing B2 4constructing B3 *64继承时的析构函数继承时的析构函数n析构函数也不被继承,派生类自行声明析构函数也不被继承,派生类自行声明n声明方法与一般(无继承关系时)类的析构函数相同。声明方法与一般(无继承关系时)类的析构函数相同。n不需要显式地调用基类的析构函数,系统会自动隐式不需要显式地调用基类的析构函数,系统会自动隐式调用。调用。n析构函数的调用次序与构

53、造函数相反。析构函数的调用次序与构造函数相反。例例 派生类析构函数举例派生类析构函数举例#include using namecpace std;class B1/基类基类B1声明声明 public:B1(int i) coutconstructing B1 iendl;B1() coutdestructing B1 endl;class B2/基类基类B2声明声明public:B2(int j) coutconstructing B2 jendl;B2() coutdestructing B2 endl;class B3/基类基类B3声明声明public:B3()coutconstructi

54、ng B3 *endl;B3() coutdestructing B3 endl;class C: public B2, public B1, public B3public:C(int a, int b, int c, int d): B1(a),memberB2(d),memberB1(c),B2(b)private:B1 memberB1;B2 memberB2;B3 memberB3;int main() C obj(1,2,3,4); 67例例 运行结果运行结果constructing B2 2constructing B1 1constructing B3 *constructin

55、g B1 3constructing B2 4constructing B3 *destructing B3destructing B2destructing B1destructing B3destructing B1destructing B2同名隐藏规则同名隐藏规则当派生类与基类中有相同成员时:当派生类与基类中有相同成员时:n若未强行指名,则通过派生类对象使用的是派生类中若未强行指名,则通过派生类对象使用的是派生类中的同名成员。的同名成员。n如要通过派生类对象访问基类中被覆盖的同名成员,如要通过派生类对象访问基类中被覆盖的同名成员,应使用基类名限定。应使用基类名限定。例例 多继承同名隐藏

56、举例多继承同名隐藏举例#include using namespace std;class B1/声明基类声明基类B1 public:/外部接口外部接口int nV;void fun() coutMember of B1endl;class B2/声明基类声明基类B2 public:/外部接口外部接口int nV;void fun()coutMember of B2endl;class D1: public B1, public B2 public:int nV;/同名数据成员同名数据成员void fun()coutMember of D1endl;/同名函数成员同名函数成员;int main

57、() D1 d1;d1.nV=1; /对象名对象名.成员名标识成员名标识, 访问访问D1类成员类成员d1.fun(); d1.B1:nV=2;/作用域分辨符标识作用域分辨符标识, 访问基类访问基类B1成员成员d1.B1:fun();d1.B2:nV=3;/作用域分辨符标识作用域分辨符标识, 访问基类访问基类B2成员成员d1.B2:fun();二义性问题二义性问题n在多继承时,基类与派生类之间,或基类之间出现同名成员时,在多继承时,基类与派生类之间,或基类之间出现同名成员时,将出现访问时的二义性(不确定性)将出现访问时的二义性(不确定性)采用虚函数或同名隐采用虚函数或同名隐藏规则来解决。藏规则来

58、解决。n当派生类从多个基类派生,而这些基类又从同一个基类派生,当派生类从多个基类派生,而这些基类又从同一个基类派生,则在访问此共同基类中的成员时,将产生二义性则在访问此共同基类中的成员时,将产生二义性采用虚基采用虚基类来解决。类来解决。B1B2B3AC二义性问题举例(一)二义性问题举例(一)class A public: void f();class B public: void f(); void g();class C: public A, piblic B public: void g(); void h();如果声明:如果声明:C c1;则则 c1.f(); 具有二义性具有二义性而而

59、c1.g(); 无二义性(同名覆盖)无二义性(同名覆盖)二义性的解决方法二义性的解决方法n解决方法一:用类名来限定解决方法一:用类名来限定c1.A:f() 或或 c1.B:f()n解决方法二:同名覆盖解决方法二:同名覆盖在在C 中声明一个同名成员函数中声明一个同名成员函数f(),f()再根据需要调用再根据需要调用 A:f() 或或 B:f()二义性问题举例(二)二义性问题举例(二)class B public: int b;class B1 : public B private: int b1;class B2 : public B private: int b2;class C : publ

60、ic B1,public B2 public: int f(); private: int d;派生类派生类C C的对象的存储结构示意图:的对象的存储结构示意图:bb1bb2dB类成员B类成员B1类成员B2类成员C类对象有二义性:有二义性:C c;c.bc.B:b无二义性:无二义性:c.B1:bc.B2:b7611.5.2 11.5.2 虚基类虚基类 如果一个派生类从多个基类派生,而这些基类又有一个共同如果一个派生类从多个基类派生,而这些基类又有一个共同 的基类,则在对该基类中声明的名字进行访问时,可能产生的基类,则在对该基类中声明的名字进行访问时,可能产生 二义性二义性7.5.2 虚基类例如:例如:class B public : int b ; ;class B1 : public B private : int b1 ; ;class B2 : public B private : i

温馨提示

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

评论

0/150

提交评论