C++程序设计课程介绍-第12章 组合与继承.ppt
《C++程序设计课程介绍-第12章 组合与继承.ppt》由会员分享,可在线阅读,更多相关《C++程序设计课程介绍-第12章 组合与继承.ppt(113页珍藏版)》请在三一办公上搜索。
1、第12章 组合与继承,组合 继承 虚函数与多态性纯虚函数与抽象类 多继承,组合,组合就是把用户定义类的对象作为新类的数据成员 组合表示一种聚集关系,是一种部分和整体(is a part of)的关系 必须用初始化列表去初始化对象成员,组合实例,定义一个复数类,而复数的虚部和实部都用有理数表示,类定义,class Complexfriend Complex operator+(Complex x,Complex y);friend istream,成员函数的实现,Complex operator+(Complex x,Complex y)Complex tmp;/利用Rational类的加法重载
2、函数完成实部和虚部的相加 tmp.real=x.real+y.real;tmp.imag=x.imag+y.imag;return tmp;,istream,复数类的使用,int main()Complex x1,x2,x3;cout x1;cout x2;x3=x1+x2;cout x1+x2=x3 endl;return 0;,第12章 组合与继承,组合 继承 虚函数与多态性纯虚函数与抽象类 多继承,派生类的概念,继承是面向对象程序设计的一个重要特征,它允许在已有类的基础上创建新的类基类、父类派生类、导出类或子类继承可以让程序员在已有类的基础上通过增加或修改少量代码的方法得到新的类,从而较
3、好地解决代码重用的问题。,派生类,单继承的格式基类成员在派生类中的访问特性 派生类对象的构造、析构与赋值操作 重定义基类的函数 派生类作为基类 将派生类对象隐式转换为基类对象,派生类的定义,一般格式:class 派生类名:派生方法 基类名/派生类新增的数据成员和成员函数;派生方法:公有派生:public私有派生:private保护派生:protected,派生实例,class base int x;public:void setx(int k);class derived1:public base int y;public:void sety(int k);,Derived1有两个数据成员:x
4、,y。有两个成员函数:setx和sety,派生类对基类成员的访问,派生类的成员函数不能访问基类的私有数据成员 protected访问特性 protected成员是一类特殊的私有成员,它不可以被全局函数或其他类的成员函数访问,但能被派生类的成员函数访问 protected成员破坏了类的封装,基类的protected成员改变时,所有派生类都要修改,派生类,单继承的格式基类成员在派生类中的访问特性 派生类对象的构造、析构与赋值操作 重定义基类的函数 派生类作为基类 将派生类对象隐式转换为基类对象,派生类对基类成员的访问性,class base int x;public:void setx(int k
5、);class derived1:public base int y;public:void sety(int k);,继承实例,定义一个二维平面上的点类型,可以设置点的位置,获取点的位置。在此基础上,扩展出一个三维空间上的点类型。,point_2d的定义,class point_2d private:int x,y;public:void setpoint2(int a,int b)x=a;y=b;int getx()return x;int gety()return y;,point_3d的定义,class point_3d:public point_2dint z;public:void
6、 setpoint3(int a,int b,int c)setpoint2(a,b);z=c;int getz()return z;,point_3d的讨论,point_3d的组成:有三个数据成员:x,y和z,有五个公有的成员函数:setpoint2,setpoint3,getx,gety和getz。point_3d的成员函数无法直接访问基类的x和y,因此在setpoint3函数中必须调用在point_2d的公有成员函数setpoint2实现。point_3d类的使用和普通类完全一样,用户不用去管这个类是用继承方式从另外一个类扩展而来,还是完全直接定义的。,Point_3d的使用,int m
7、ain()point_2d p1;point_3d p2;p1.setpoint2(1,2);cout p1:(p1.getx(),p1.gety()endl;p2.setpoint3(1,2,3);cout p2:(p2.getx(),p2.gety(),p2.getz()endl;return 0;,P1:(1,2)P2:(1,2,3),派生类,单继承的格式基类成员在派生类中的访问特性 派生类对象的构造、析构与赋值操作 重定义基类的函数 派生类作为基类 将派生类对象隐式转换为基类对象,派生类的构造函数和析构函数,由于派生类继承了其基类的成员,所以在建立派生类的实例对象时,必须初始化基类继承
8、的数据成员。派生类对象析构时,也必须析构基类对象。派生类不继承基类的构造函数、析构函数和赋值运算符,但是派生类的构造函数、析构函数和赋值运算符能调用基类的构造函数、析构函数和赋值运算符。,派生类的构造函数,基类成员的初始化由基类的构造函数完成。派生类的构造函数调用基类的构造函数完成基类成员的初始化。派生类构造函数可以隐式调用基类缺省的构造函数,也可以在派生类的构造函数的初始化列表显式地调用基类的构造函数。,构造函数的格式,派生类构造函数的格式:派生类构造函数名(参数表):基类构造函数名(参数表)。基类构造函数中的参数表通常来源于派生类构造函数的参数表,也可以用常数值。如果构造派生类对象时调用的
9、是基类的缺省构造函数,则可以不要初始化列表。如果派生类新增的数据成员中含有对象成员,则在创建对象时,先执行基类的构造函数,再执行成员对象的构造函数,最后执行自己的构造函数体。,派生类构造实例,定义一个二维平面上的点类,并从它派生出一个圆类,point2.h,/Definition of class Point#ifndef POINT2_H#define POINT2_Hclass Point public:Point(int=0,int=0);/default constructor Point();/destructorprotected:/accessible by derived cl
10、asses int x,y;/x and y coordinates of Point;#endif,point2.cpp,#include point2.h/Constructor for class PointPoint:Point(int a,int b)x=a;y=b;cout Point constructor:x,y endl;/Destructor for class PointPoint:Point()cout Point destructor:x,y endl;,circle2.h,#ifndef CIRCLE2_H#define CIRCLE2_H#include poin
11、t2.hclass Circle:public Point public:/default constructor Circle(double r=0.0,int x=0,int y=0);Circle();private:double radius;#endif,circle2.cpp,#include circle2.h/Constructor for Circle calls constructor for PointCircle:Circle(double r,int a,int b):Point(a,b)/call base-class Constructor radius=r;/s
12、hould validatecout Circle constructor:radius is radius x,y endl;/Destructor roi class CircleCircle:Circle()cout Circle destructor:radius is radius x,y endl;,Circle类的应用,#include point2.h“#include circle2.h int main()/Show constructor and destructor calls for Point Point p(11,22);cout endl;Circle circ
13、le1(4.5,72,29);cout endl;Circle circle2(10,5,5);cout endl;return 0;,Point constructor:11,22 Point destructor:11,22 Point constructor:72,29 Circle constructor:radius is 4.5 72,29Point constructor:5,5 Circle constructor:radius is 10 5,5 Circle destructor:radius is 10 5,5 Point destructor:5,5 Circle de
14、structor:radius is 4.5 72,29 Point destructor:72,29,派生类构造函数的构造规则,若基类使用缺省或不带参数的构造函数,则在派生类定义构造函数是可略去:基类构造函数名(参数表)。此时若派生类也不需要构造函数,则可不定义构造函数。当基类构造函数需要参数,而派生类本身并不需要构造函数时,派生类还必须定义构造函数。该函数只是起了一个参数传递作用。如果省略了派生类的构造函数,那么就由派生类的默认构造函数调用基类的默认构造函数。,派生类实例,定义一个图书馆系统中的读者类,每个读者的信息包括:卡号、姓名、单位、允许借书的数量以及已借书记录。学生最多允许借5本书
15、,教师最多允许借10本书。,设计过程,系统中有两类读者:学生读者和教师读者。这两类读者有一部分内容是相同的:卡号、姓名和单位。可将两类读者的共同部分内容设计成一个基类。学生读者和教师读者从基类派生,增加已借书的数量以及已借书记录两个数据成员,并将允许借书的数量定义为整个类共享的常量,基类的设计,class readerint no;char name10;char dept20;public:reader(int n,char*nm,char*d)no=n;strcpy(name,nm);strcpy(dept,d);,教师读者类的设计,class readerTeacher:public r
16、eaderenum MAX=10;int borrowed;int recordMAX;public:readerTeacher(int n,char*nm,char*d):reader(n,nm,d)borrowed=0;bool bookBorrow(int bookNo);bool bookReturn(int bookNo);void show();/显示已借书信息;,学生读者类的设计,class readerStudent:public reader enum MAX=5;int borrowed;int recordMAX;public:readerStudent(int n,ch
17、ar*nm,char*d):reader(n,nm,d)borrowed=0;bool bookBorrow(int bookNo);bool bookReturn(int bookNo);void show();/显示已借书信息;,派生类对象的析构,派生类的析构函数值析构自己新增的数据成员,基类成员的析构由基类的析构函数析构派生类析构函数会自动调用基类的析构函数派生类对象析构时,先执行派生类的析构函数,再执行基类的析构函数,派生类构造函数和析构函数的构造规则实例,class base public:base()coutconstructing basen;base()coutdestruct
18、int basen;class derive1:public basepublic:derive1()coutconstructing derive1n;derive1()coutdestructing derive1n;main()derive1 op;return 0;,执行结果,constructing base constructing derive1 destructing derive1 destructing base,派生类,单继承的格式基类成员在派生类中的访问特性 派生类对象的构造、析构与赋值操作 重定义基类的函数 派生类作为基类 将派生类对象隐式转换为基类对象,重定义基类的
19、函数,派生类是基类的扩展,可以是保存的数据内容的扩展,也可以是功能的扩展。当派生类对基类的某个功能进行扩展时,他定义的成员函数名可能会和基类的成员函数名重复。如果只是函数名相同,而原型不同时,系统认为派生类中有两个重载函数。如果原型完全相同,则派生类的函数会覆盖基类的函数。这称为重定义基类的成员函数。,实例,定义一个圆类型,用于保存圆以及输出圆的面积和周长。在此类型的基础上派生出一个球类型,可以计算球的表面积和体积。,圆类的设计,数据成员:圆的半径成员函数:由于需要提供圆的面积和周长,需要提供两个公有的成员函数。除了这些之外,还需要一个构造函数,圆类的定义,class circle prote
20、cted:double radius;public:circle(double r=0)radius=r;double getr()return radius;double area()return 3.14*radius*radius;double circum()return 2*3.14*radius;,球类的定义,class ball:public circle public:ball(double r=0):circle(r)double area()return 4*3.14*radius*radius;double volumn()return 4*3.14*radius*rad
21、ius*radius/3;,Ball类的构造函数,Ball类没有新增加数据成员,因而不需要构造函数。但基类的构造函数需要参数,所以ball类必须写构造函数Ball类构造函数的作用是为circle类的构造函数传递参数,Ball类的area函数,Ball类包含了两个原型完全一样的area函数。一个是自己定义的,一个是从circle类继承来的当对ball类的对象调用area函数时,调用的是ball类自己定义的area函数,派生类引用基类的同名函数,派生类中重新定义基类的成员函数时,它的功能往往是基类功能的扩展。为完成扩展的工作,派生类版本通常要调用基类中的该函数版本。引用基类的同名函数必须使用作用域
22、运算符,否则会由于派生类成员函数实际上调用了自身而引起无穷递归。这样会使系统用光内存,是致命的运行时错误。,实例,在circle类的基础上定义一个cylinder类。可以计算圆柱体的表面积和体积 设计考虑:存储圆柱体可以在圆的基础上增加一个高度。圆柱体的表面积是上下两个圆的面积加上它的侧面积圆柱体的体积是底面积乘上高度。而求圆的面积的函数在circle类中已经存在。,Cylinder类的定义,class cylinder:public circle double height;public:cylinder(double r=0,double h=0):circle(r)height=h;do
23、uble geth()return height;double area()return 2*circle:area()+circum()*height;double volumn()return circle:area()*height;,Ball和cylinder类的使用,int main()circle c(3);ball b(2);cylinder cy(1,2);cout circle:r=c.getr()endl;cout area=c.area()tcircum=c.circum()endl;cout ball:r=b.getr()endl;cout area=b.area()t
24、volumn=b.volumn()endl;cout cylinder:r=cy.getr()th=cy.geth()endl;cout area=cy.area()tvolumn=cy.volumn()endl;return 0;,执行结果,circle:r=3area=28.26 circum=18.84ball:r=2area=50.24 volumn=33.4933cylinder:r=1area=18.84 volumn=6.28,派生类,单继承的格式基类成员在派生类中的访问特性 派生类对象的构造、析构与赋值操作 重定义基类的函数 派生类作为基类 将派生类对象隐式转换为基类对象,派生
25、类作为基类,基类本身可以是一个派生类,如:class base class d1:public base class d2:public d1 每个派生类继承他的直接基类的所有成员。如果派生类的基类是一个派生类,则每个派生类只负责他的直接基类的构造,依次上溯。当构造d2类的对象时,会先调用d1的构造函数,而d1的构造函数执行时又会先调用base的构造函数。因此,构造d2类的对象时,最先初始化的是base的数据成员,再初始化d1新增的成员,最后初始化d2新增的成员。析构的过程正好相反。,实例,#include using namespace std;class base int x;public
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C+程序设计课程介绍-第12章 组合与继承 C+ 程序设计 课程 介绍 12 组合 继承
链接地址:https://www.31ppt.com/p-2732197.html