《面向对象程序设计》讲义11.ppt

上传人:本田雅阁 文档编号:2155725 上传时间:2019-02-23 格式:PPT 页数:58 大小:750.51KB
返回 下载 相关 举报
《面向对象程序设计》讲义11.ppt_第1页
第1页 / 共58页
《面向对象程序设计》讲义11.ppt_第2页
第2页 / 共58页
《面向对象程序设计》讲义11.ppt_第3页
第3页 / 共58页
亲,该文档总共58页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《《面向对象程序设计》讲义11.ppt》由会员分享,可在线阅读,更多相关《《面向对象程序设计》讲义11.ppt(58页珍藏版)》请在三一文库上搜索。

1、面向对象程序设计讲义,第 11 章,11.1 派生的概念 继承是对象类间的一种相关关系,是派生关系,并具有以下性质: (1)类间的共享特性; (2)类间的细微区别; (3)类间的层次关系。,第 11 章 继承与类的派生,11.1.1 为什么使用继承 1. 继承可以重用先前项目的代码,如果原来的代码不能完全满 足要求,还可以做少量的修改,满足不断变化的具体应用要求, 从而提高程序设计的灵活性,避免不必要的重复设计。 2. 若某个项目使用了几个非常相似或稍有不同的类,就可以通 过派生类的继承性达到函数和数据继承的目的。 11.1.2 派生类的定义 1. 派生新类的特性: (1)新类可以在基类所提供

2、的基础上包含新的成员; (2)在新的类中可隐藏基类的任何函数成员; (3)可为新的类重新定义成员函数。,2. 派生类的定义 class x / ; class y:x / ; 例如:有一个整数链表的类,如下所示: struct node /每一结点结构 int val; node *next; ,class List node *elems; /链表头指针 public: List(); List(); bool insert(int); /在表前插入一个结点 bool deletes(int); /在表中删除一个结点 bool contains(int); /在表中查找一个结点 ; 由整型链

3、表类派生出整型集合类,定义如下: class set:List int card; /表示集合中的元素个数 public: bool insert(int); / ;,11.1.3 派生类对基类成员的访问权 基类的私有成员派生类及派生类的使用者都无权访问。 class x int x,y; public: void get_ij(); / ; class y: x int k; public: void make_k(); / ;,void y:make() k=i*j; /非法 1. 私有派生 class x int a; public: int get() return a; / ;,cl

4、ass y: x int b; / public: void make() b=get()+10; / ; void f() x x1; y y1; y1.make(); y1.get(); /错误 ,2. 公有派生 class y:public x / ; 基类中的所有公有成员在派生类中都是公有的。,派生类对基类成员的访问权限:,例1 #include class base /定义一个基类 int x1,x2; public: void assign(int p1,int p2) /为私有数据赋值 x1=p1; x2=p2; int inc1() return +x1; /返回增1后的x1值

5、 int inc2() return +x2; /返回增1后的x2值 void display() /输出x1,x2之值 cout“base x1=”x1“x2=”x2“n”; ;,class derive1:base /定义一个私有派生类 int x3; public: derive1(int p3) x3=p3; void assign(int p1,int p2) /为基类数据赋值 base:assign(p1,p2); /调用基类成员函数 int inc1() return base:inc1(); /调用基类成员函数, int inc2() return base:inc2(); /

6、对x1,x2增值 int inc3() return +x3; /求x3增值 void display() /输出x3之值 cout“derive1 x3=”x3“n”; ;,class derive2:public base /定义一个公有派生类 int x4; public: derive2(int p4) x4=p4; int inc1() int temp=base:inc1(); /不断调用基类的inc1() temp=base:inc1(); temp=base:inc1(); temp=base:inc1(); int inc4() return +x4; /对x4增值 void

7、 display() base:display(); /先调用基类的 display() cout“derive2 x4=”x4“n”; ;,main() base p; /定义一个base类对象 p.assign(-2,-2); / p的x1,x2取-2 p.display(); /显示基类成员 derive1 d1(-4); /定义派生类对象d1,并调用构造函数为x3赋值 d1.assign(10,10); /给基类成员赋值 d1.inc1(); /对x1增值 d1.display(); /显示d1对象的私有成员 derive2 d2(5); /定义公有派生类对象d2 d2.assign(

8、-6,-6); /给d2对象的基类对象的成员赋值 d2.display(); /先显示d2对象的基类对象的成员,再显示本身 /对象的成员 d2.inc1(); /对基类的成员x1四次赋值,d2.inc2(); /实际上执行的是d2.base:inc2(); d2.display(); d2.base:inc1(); /显式调用其基类的成员函数 d2.display(); 运行结果为: base x1=-2 x2=-2 derive1 x3=-4 base x1=-6 x2=-6; derive2 x4=5 base x1=-2 x2=-5 derive2 x4=5 base x1=-1 x2=

9、-5 derive2 x4=5,11.1.4 派生类的构造函数和析构造函数 1. 派生类构造函数及析构造函数的构造规则 (1)构造函数 以下两种情况必须定义构造函数 (a) 派生类本身需要构造函数。 (b) 在定义派生类对象时,其相应的基类对象需要调用带有参数的构造函数。 构造函数的格式: 派生类构造函数(变元表):基类构造函数(变元表),对象成员1的构造函数(变元表),对象成员n的构造函数(变元表) / ,构造函数的执行顺序: 先祖先(基类),再客人(对象成员),后自己(派生类本身)。 (2)析构函数 析构函数的执行顺序: 先自己(派生类本身),再客人(对象成员),后祖先(基类)。 2. 带

10、有构造函数和析构函数的类的派生举例 例1 #include class data /定义data类 int x; public: data(int x) data:x=x; /基类构造函数 cout“class datan”; ,class a data d1; /d1为data类的对象 public: a(int x):d1(x) /定义构造函数,缀上对象成员的构造函数 cout“class an”; class b:public a /定义b类 data d2; /d2为data类的对象 public: b(int x):a(x),d2(x) /缀上基类和对象成员的构造函数 cout“cl

11、ass bn”; ;,class c :public b /定义c类 public: c(int x):b(x) /缀上基类b的构造函数 cout“class cn”; ; main() c object(5); / 运行结果: class data class a class data class b class c,例2 #include class device /定义基类 public: device() cout“class devicen”; ; class comm_device:public device /定义派生类 public: comm_device() /因基类构造函

12、数无参数,故无需缀上 cout“class comm_devicen”; ; class gra_device:public device /定义派生类 public: /无构造函数 /. ;,main() comm_device d1; gra_device d2; 运行结果为: class device class comm_device class device,11.2 派生类对基类成员的继承 11.2.1 如何访问基类私有成员 1 在定义体中增加保护段 例1 /-派生类对基类成员的继承- #include #pragma hdrstop #include “U11_2_0.h“ /-

13、 #pragma package(smart_init) #pragma resource “*.dfm“ Tf11_2_1_1 *f11_2_1_1; /*-,class x protected: int i,j; public: x(int i,int j) x:i=i;x:j=j; void print(int ii) f11_2_1_1-Canvas-TextOut(20,20*ii,“i=“+IntToStr(i); f11_2_1_1-Canvas-TextOut(80,20*ii,“j=“+IntToStr(j); ;,class y:public x int k; public

14、: y(int i,int j):x(i,j) k=i*j; void print(int ii) f11_2_1_1-Canvas-TextOut(20,20*ii,“i=“+IntToStr(i); f11_2_1_1-Canvas-TextOut(80,20*ii,“j=“+IntToStr(j); 11_2_1_1-Canvas-TextOut(140,20*ii,“k=“+IntToStr(k); ;,class z:y public: z(int i,int j):y(i,j) /专为执行基类构造函数而设 void print1(int ii) /可以访问i,j,但不能访问k f1

15、1_2_1_1-Canvas-TextOut(20,20*ii,“i=“+IntToStr(i); f11_2_1_1-Canvas-TextOut(80,20*ii,“j=“+IntToStr(j); void print(int ii) /调用y中的print()访问k y:print(ii); ; /*-,_fastcall Tf11_2_1_1:Tf11_2_1_1(TComponent* Owner) : TForm(Owner) /- void _fastcall Tf11_2_1_1:btnRunClick(TObject *Sender) z z1(10,20); y y1(2

16、3,45); y1.print(1); z1.print(2); z1.print1(3); ,/- void _fastcall Tf11_2_1_1:btnEndClick(TObject *Sender) Close(); /- 运行结果为: i=23 j=45 k=1035 i=10 j=20 k=200 i=10 j=20,2. 将需访问基类私有成员的派生类成员函数声明为基类的友元 例如: class set class node int val; node *next; ; class list node *elems; public: / friend set:operator

17、+(set ,class set:public list int card; public: / set operator +(set ,11.2.2 通过访问声明调整访问域 (1) 访问声明仅仅调整名字的访问,不可为它说明任何类型;若名字为成员函数,在访问声明时也不准说明任何类型。 (2) 访问声明只能调整基类的保护段和公有段成员在派生类中的访问域。 (3) 访问声明仅仅用于在派生类中调整名字的访问权限,不允许在派生类中降低或提升基类成员的可访问性。 (4) 对重载函数名的访问声明将调整基类中具有该名的所有函数的访问域。 (5) 若在派生类中具有与基类中同名的函数,则基类中的此函数不允许在派

18、生类中进行访问声明。,11.3 多 继 承 11.3.1 多继承的概念 11.3.2 多继承的定义 例如: class c:a,b / ;,例1 #include class x protected: int a; public: void make(int i) a=i; ; class y protected: int a; public: void make(int i) a=i; ;,class z:public x,public y / public: int make(int i) return x:a*y:a; ; main() z z1; z1.x:make(10); z1.y

19、:make(20); coutz1.make()“n”; ;,例2 #include class x int a; public: void seta(int x) a=x; void showa() cout“a=”“n”; ; class y int b; public: void setb(int x) b=x; void showb() cout“b=”“n”; ;,class z:public x, y / int c; public: void setc(int x,int y) c=x; setb(y); / y类的私有成员z类无权访问,因 /此调用setb()对y类中的b赋值

20、void showc() showa(); showb(); cout“c=”c“n”; ;,main() z obj; obj.seta(5); /调用的是基类x中的成员函数,因x为公有派生 obj.setc(7,9); obj.showc(); obj.showa(); /调用x中的成员函数 /obj.showb(); /此处不能调用y:showb(),因为z对y是私有派生 return 1; 运行结果为: a=5 b=9 c=7 a=5,11.3.3 多继承的构造函数与析构函数 1. 构造函数的定义 2. 构造函数与析构函数的执行顺序 举例说明如下: #include class x /

21、 public: x() cout“the constructor of class x!n”; x() cout“the destructor of class x!n”; / ;,class y / public: y() cout“the constructor of class y!n”; y() cout“the destructor of class y!n”; / ; class z:public x,public y / public: z() cout“the constructor of class z!n”; z() cout“the destructor of clas

22、s z!n”; / ;,main() z obj; 运行结果为: the constructor of class x / the constructor of class y / the constructor of class z / the destructor of class z the destructor of class y the destructor of class x,3. 构造函数和析构函数多继承举例 /- #include #pragma hdrstop #include “U11_3_3.h“ /- #pragma package(smart_init) #pra

23、gma resource “*.dfm“ Tbc11_3_3_2 *bc11_3_3_2; /*-,struct vecelem /向量结点 char *index; short value; ; class assocvec /定义相关向量类 vecelem *elems; int dim; int used; public: assocvec(int dim); assocvec(); short ,class matrix /定义矩阵类 short rows,cols; double *elems; public: matrix(short rows,short cols); matri

24、x(); double ,assocvec:assocvec(int dim) assocvec:dim=dim; used=0; elems=new vecelemdim; assocvec:assocvec() for(int i=0;iused;+i) delete elemsi.index; delete elems; ,short ,matrix:matrix(short rows,short cols) matrix:rows=rows; matrix:cols=cols; elems=new doublerows*cols; matrix:matrix() delete elem

25、s; double ,void matrix:print() for(int r=1;rrows;r+) for(int c=1;ccols;c+) bc11_3_3_2-Canvas- TextOut(60*c,20*r, FloatToStr(*this)(r,c); table:table(short entries):assocvec(entries), matrix(entries,entries) /派生类构造函数,缀上基类的构造函数,double /*- _fastcall Tbc11_3_3_2:Tbc11_3_3_2(TComponent* Owner) : TForm(Ow

26、ner) /-,void _fastcall Tbc11_3_3_2:btnRunClick(TObject *Sender) table tab(3); tab(“Beijing“,“Shanghai“)=3.55; tab(“Beijing“,“Qingdao“)=12.45; tab(“Shanghai“,“Beijing“)=2.34; tab(“Shanghai“,“Qingdao“)=10.31; tab(“Qingdao“,“Shanghai“)=9.32; tab(“Qingdao“,“Beijing“)=15.36; tab.print(); ,/- void _fastca

27、ll Tbc11_3_3_2:btnEndClick(TObject *Sender) Close( ); /-,11.3.4 虚基类 1. 为什么要使用虚基类 #include calss x protected: int a; public: x() a=10; ; calss x1:public x public: x1() couta“n”; ;,calss x2:public x public: x2() couta“n”; ; calss y:x1,x2 public: y() couta“n”; /错,x1:a或x2:a ; main() y obj; ,2. 虚基类的概念 关键

28、字:virtual 例如: class x1: virtual public x / ; class x2: virtual public x / ;,3. 虚基类的初始化 派生类构造函数的调用次序应遵循下述原则: (1)虚基类的构造函数在非虚基类之前调用; (2)若同一层次中包含多个虚基类,这些虚基类的构造函数按它们说明的次序调用; (3)若虚基类由非虚基类派生而来,则仍然先调用基类构造函数,再调用派生类的构造函数。 举例说明如下: #include class base public: base() cout“this is base class!n”; ;,class base2 pub

29、lic: base2() cout“this is base2 class!n”; ; class level1:public base2,virtual public base public: level1() cout“this is level1 class!n”; ; class level2:public base2,virtual public base public: level2() cout“this is level2 class!n”; ;,class toplevel:public level1, virtual public level2 public: toplevel () cout“this is toplevel class!n”; ; main() toplevel topobj; ,运行结果为: this is base class! this is base2 class! this is level2 class! this is base2 class! this is level1 class! this is toplevel class!,

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

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1