1、派生类与继承,1、 类之间的关系,2、 派生类的概念,3、 派生类的构造函数与析构函数,4、 调整派生类中基类成员的访问属性,5、 多重继承,6、 赋值兼容规则,兰州理工大学计算机与通信学院 张其文,1、类之间的关系,has-A,uses-A 和 is-Ahas-A(包含关系),用以描述一个类由多个“部件类”构成。实现has-A关系用类成员表示,即一个类中的数据成员是已定义的类。uses-A(一个类部分地使用另一个类),通过类之间成员函数的相互联系,定义友员或对象参数传递实现。is-A(继承)。关系具有传递性,不具有对称性。,非对称性:不是所有植物都属于蕨类。,传递性: 高等植物、蕨类植物、芒
2、萁都是植物,具有植物的共同特征。,植物,继承关系,继承 是类之间定义的一种重要关系。一个 B 类继承A类,或称从类 A 派生类 B 类 A 称为基类(父类),类 B 称为派生类(子类),B1,B2 的基类,A 的派生类 C1,C2,C3 的基类,A 的派生类(单继承) C3的基类,B1,B2 的派生类(多继承),B1 的派生类,继承关系,class person protected:char name10;int age;char sex;public:void print( ); ;,class employee protected:char name10;int age;char sex;
3、char department20;float salary;public:void print( ); ;,为什么要用继承?,继承:保持已有类的特性而构造新类的过程。 派生:在已有类的基础上新增自己的特性而产生新类的过程。 继承的目的:实现代码重用。 派生的目的:当新的问题出现,原有程序无法解决(或不能完全解决)时,需要对原有程序进行改造。,2、派生类的概念,继承关系的语法形式class 派生类名 : 基类名表数据成员和成员函数声明;,派生类的声明,派生类的功能: 可以增加新的数据成员; 可以增加新的成员函数; 可以重新定义基类中已有的成员函数; 可以改变现有成员的属性。,基类名表 构成 访
4、问控制 基类名1,访问控制 基类名2 , ,访问控制 基类名n,访问控制:表示派生类对基类的继承方式 public 公有继承private 私有继承protected 保护继承,派生类的声明,派生类对基类成员的使用,与继承访问控制和基类中成员性质有关; 公有继承 基类的公有成员派生类的公有成员基类的保护成员派生类的保护成员 私有继承 基类的公有成员和保护成员派生类的私有成员 保护继承 基类的公有成员和保护成员派生类的保护成员 不论什么方式继承基类,派生类都不能直接使用基类的私有成员。,访问控制,(1)公有继承,#include class A public :void get_XY() cou
5、t x y ; void put_XY() cout h ; int get_V() return v ; void make_V() make_S(); v = get_S() * h ; / 使用基类成员函数protected: int h, v; ;,公有继承的测试,#include class A public :void get_XY() cout x y ; void put_XY() cout h ; int get_V() return v ; void make_V() make_S(); v = get_S() * h ; / 使用基类成员函数protected: int
6、h, v; ;,保护数据成员 在类层次中可见,公有继承的测试,void 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() ;objB.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_
7、V() endl ; ,公有继承的测试,void 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() ;objB.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 ;
8、,公有继承的测试,void 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() ;objB.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 ; ,x y,公有继承的测
9、试,void 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() ;objB.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 ; ,x y,s,公有继承的测试,voi
10、d 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() ;objB.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 的 数据成员操作,x y,s,
11、h v,公有继承的测试,void 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() ;objB.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 ; ,调用基类A成员
12、函数 对 objB 的数据成员操作,x y,s,h v,公有继承的测试,void 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() ;objB.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
13、.get_V() endl ; ,调用派生类B成员函数 对 objB 的数据成员操作,x y,s,h v,公有继承的测试,void 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() ;objB.make_S() ;cout “S = “ objB.get_S() endl ;cout “It is object_C :n“ ;objC.get_XY() ;objC.get_H();objC.m
14、ake_V() ;cout “V = “ objC.get_V() endl ; ,调用基类A成员函数 对 objC 的数据成员操作,x y,s,h v,公有继承的测试,void 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() ;objB.make_S() ;cout “S = “ objB.get_S() endl ;cout “It is object_C :n“ ;objC.get_X
15、Y() ;objC.get_H();objC.make_V() ;cout “V = “ objC.get_V() endl ; ,调用派生类C成员函数 对 objC 的数据成员操作,x y,s,h v,公有继承的测试,void 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() ;objB.make_S() ;cout “S = “ objB.get_S() endl ;cout “It is
16、 object_C :n“ ;objC.get_XY() ;objC.get_H();objC.make_V() ;cout “V = “ objC.get_V() endl ; ,x y,s,h v,公有继承的测试,(2)私有继承,#include class 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() g
17、et_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 ;,私有继承的测试,#include class 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() r
18、eturn 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 ;,调用基类成员函数,私有继承的测试,#include class A public :void get_XY() cout x y ; void put_XY() cout “x = “ x “, y = “ y n ; protected: int x, y ; ; class B
19、 : 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 ;,访问私有数据成员,私有继承的测试,#include class A public :void get_XY() cout x y ; void put_XY() cout “x = “ x “, y = “ y n
20、 ; protected: int x, y ; ; 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 ;,私有继承的测试,#include class A public: A() x=1; int out() return x ; void addX(
21、) 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 ; ,基类的私有数据成员 不能在派生类中直接访问 但派生类对象建立私有数据空间,私有继承的测试,#include clas
22、s 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 ;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 ; ,私有继承的测
23、试,#include class 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 ;cout “a.x=“ a.out() endl ;B b ;b.addX() ; b.addY() ;cout “b.x=“ b.A:out() endl ;cout “b.y=“ b.out()
24、 endl ; ,调用构造函数 对数据成员赋值,私有继承的测试,#include class 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 ;cout “a.x=“ a.out() endl ;B b ;b.addX() ; b.addY() ;cout “b.x=“ b.A:o
25、ut() endl ;cout “b.y=“ b.out() endl ; ,创建派生类对象 调用基类 派生类构造函数 b.x = 1 b.y = 1,私有继承的测试,#include class 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 ;cout “a.x=“ a.out
26、() endl ;B b ;b.addX() ; b.addY() ;cout “b.x=“ b.A:out() endl ;cout “b.y=“ b.out() endl ; ,调用基类公有成员函数 b.x +,私有继承的测试,#include class 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 ; ; vo
27、id 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 ; ,调用派生类公有成员函数 b.y +,私有继承的测试,#include class 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
28、 addY() y+; 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 ; ,调用基类版本同名函数 返回 b.x 的值,私有继承的测试,#include class A public: A() x=1; int out() return x ; void addX() x+; private: int x ; ; class B : public A public
29、: B() y=1; int out() return y ; void addY() y+; 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 ; ,调用派生类版本同名函数 返回 b.y 的值,私有继承的测试,(3)保护继承,3、派生类的构造函数和析构函数,基类的构造函数和析构函数都不被继承,需要在派生类中重新定义。由于派生类继承了基类的成员,在初始化时,要同时初
30、始化基类成员。 声明派生类构造函数时,除了需要对本类中新增成员进行初始化外,还要对基类成员初始化。,派生类的构造函数,派生类构造函数声明的一般语法形式如下: :(参数总表):基类名1(参数表1),.,基类名n(参数表n),内嵌对象名1(内嵌对象参数表1),.,内嵌对象名m(内嵌对象参数表m) 派生类新增成员的初始化语句; ,派生类的构造函数,其中: 派生类的构造函数名与派生类名相同。 参数总表需要列出初始化基类数据、新增内嵌对象数据及新增一般成员数据所需要的全部参数。 冒号之后,列出需要使用参数进行初始化的基类名和内嵌成员名及各自的参数表,各项之间用逗号分隔。,派生类构造函数的执行顺序:(1)
31、先调用基类的构造函数;(2)然后按照数据成员的声明顺序,依次调用数据成员的构造函数;(3)最后执行派生类构造函数的函数体。 注意:构造函数的执行顺序只与成员声明的顺序有关,而与初始化表中各项的排列顺序无关。 常量成员、引用成员、内嵌对象,只能通过初始化表的方法初始化。,派生类的构造函数,基类 对象成员 派生类,析构函数也不被继承,派生类自行声明。声明方法与一般(无继承关系时)类的析构函数相同。 派生类析构函数执行时将自动调用基类及内嵌对象的析构函数,系统会自动隐式调用,因此不必显式调用。 析构函数的调用次序与构造函数相反。,派生类的析构函数,/构造函数调用顺序测试,构造函数无参数 #inclu
32、de class Base public : Base ( ) cout “Base created.n“ ; ; class D_class : public Base public : D_class ( ) cout “D_class created.n“ ; ; void main ( ) D_class d1 ; , 调用基类构造函数,/ 构造函数调用顺序测试,构造函数无参数 #include class Base public : Base ( ) cout “Base created.n“ ; ; class D_class : public Base public : D_cl
33、ass ( ) cout “D_class created.n“ ; ; void main ( ) D_class d1 ; , 调用派生类构造函数,#include class parent_class int data1 , data2 ;public :parent_class ( int p1 , int p2 ) data1 = p1; data2 = p2; int inc1 () return + data1; int inc2 () return + data2 ; void display () cout “data1=“ data1 “ , data2=“ data2 e
34、ndl ; ; 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 ( ) return parent_class : inc1 ( ) ; int inc3 ( ) return + data3 ; void display (
35、) parent_class : display ( ) ; data4.display ( ) ;cout “data3=“ data3 endl ; ; void main ( ) derived_class d1 ( 17 , 18 , 1 , 2 , -5 ) ; d1 . inc1 ( ) ; d1 . display ( ) ; ,带参数构造函数调用顺序测试,#include class parent_class int data1 , data2 ;public :parent_class ( int p1 , int p2 ) data1 = p1; data2 = p2; i
36、nt inc1 () return + data1; int 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
37、, p4 ) data3 = p5 ; int inc1 ( ) 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 ( ) ; ,int data1 , data
38、2 ;,int data3 ;,parent_class data4 ;,带参数构造函数调用顺序测试,带参数构造函数调用顺序测试,#include class parent_class int data1 , data2 ;public :parent_class ( int p1 , int p2 ) data1 = p1; data2 = p2; int inc1 () return + data1; int inc2 () return + data2 ; void display () cout “data1=“ data1 “ , data2=“ data2 endl ; ; cla
39、ss 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 ( ) return parent_class : inc1 ( ) ; int inc3 ( ) return + data3 ; void display ( ) parent_cl
40、ass : display ( ) ; data4.display ( ) ;cout “data3=“ data3 endl ; ; void main ( ) derived_class d1 ( 17 , 18 , 1 , 2 , -5 ) ; d1 . inc1 ( ) ; d1 . display ( ) ; ,class parent_class int data1 , data2 ;public :parent_class ( int p1 , int p2 ) data1 = p1; data2 = p2; int inc1 () return + data1; int inc
41、2 () return + data2 ; void display() cout“data1=“data1“ , data2=“data2endl ; ;,基类有一个 带参数的构造函数,带参数构造函数调用顺序测试,#include class parent_class int data1 , data2 ;public :parent_class ( int p1 , int p2 ) data1 = p1; data2 = p2; int inc1 () return + data1; int inc2 () return + data2 ; void display () cout “d
42、ata1=“ 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 ( ) return parent_class : inc1 ( ) ; int inc3 ( )
43、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 ( ) ; ,class parent_class int data1 , data2 ;public :parent_class ( int p1 , int p2 ) data1 = p1; data
44、2 = p2; int inc1 () return + data1; int inc2 () return + data2 ; void display() cout“data1=“data1“ , data2=“data2endl ; ;,成员函数 数据成员自增,#include class parent_class int data1 , data2 ;public :parent_class ( int p1 , int p2 ) data1 = p1; data2 = p2; int inc1 () return + data1; int inc2 () return + data2
45、 ; 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 ( ) return parent_class
46、: 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 ( ) ; ,class derived_class : private parent_class int data3 ;parent_class da
47、ta4 ;public:derived_class ( int p1 , int p2 , int p3 , int p4 , int p5 ): parent_class ( p1 , p2 ) , data4 ( p3 , p4 ) data3 = p5 ; int inc1 ( ) return parent_class : inc1 ( ) ; int inc3 ( ) return + data3 ; void display ( ) parent_class : display ( ) ; data4.display ( ) ;cout “data3=“ data3 endl ; ;,