第八章继承与派生
C++第08章+继承与派生

10
第八章 继承与派生
基类成员在派生类中的存取权限
(1) 无论何种派生方式,基类的私有成员在派生类中不 能访问;基类的保护成员和公有成员在派生类内部可进 行存取。 (2) 私有派生使基类的保护成员和公有成员都成为派生 类的私有成员,在派生类中可直接访问,在类外不能访 问。一般情况下,私有派生使用较少,它中止了基类功 能的进一步派生。 (3) 保护派生使基类的保护成员和公有成员都成为派生 类的保护成员,在派生类中可直接访问,在类外不能访 问。它与私有派生的不同表现在进一步派生时。 (4) 公有派生使基类的保护成员和公有成员在派生类中 不变,仍然是保护成员和公有成员。在类外可访问公有 11 成员,不可访问保护成员。
26
第八章 继承与派生
3. 赋值兼容规则 派生类对象间的赋值操作依据下面的原则: (1) 如果派生类有自己的赋值运算符的重载定义, 即按该重载函数处理。 (2) 派生类未定义自己的赋值操作,而基类定义了 赋值操作,则系统自动定义派生类赋值操作,其中 基类成员的赋值按基类的赋值操作进行。 (3) 二者都未定义专门的赋值操作,系统自动定义 缺省赋值操作。
生类继承的成员仍是某类的友元。
25
第八章 继承与派生
2. 静态成员的继承 如果基类的静态成员是公有的或是保护的,则 它们被其派生类继承为派生类的静态成员。即: (1) 这些成员通常用<类名>::<成员名>方式引 用或调用(在派生类的访问属性为public时)。 (2) 这些成员无论有多少个对象被创建,都只有一 个拷贝。它为基类和派生类的所有对象共享。
13
第八章 继承与派生
例:
雇员
兼职技术人员
管理人员
销售人员
销售经理
《继承与派生 》课件

目录
CONTENTS
• 继承与派生的基本概念 • 继承的方式 • 派生类的构造函数和析构函数 • 继承与多态 • 继承与重载
01
继承与派生的基本 概念
继承的定义
继承是面向对象编程中的一个重 要概念,它允许一个类(子类) 继承另一个类(父类)的属性和
方法。
通过继承,子类可以复用父类的 代码,减少代码冗余,提高代码
保护继承
总结词
保护继承是指基类的保护成员在派生类 中保持保护属性,可以被派生类和派生 类的对象访问。
VS
详细描述
保护继承时,基类的保护成员在派生类中 保持保护属性,可以被派生类和派生类的 对象访问。这种继承方式使得基类的保护 成员成为派生类的保护成员,可以被派生 类和派生类的对象访问。因此,派生类可 以继承基类的保护成员函数和变量。
03
派生类的构造函数 和析构函数
派生类的构造函数
派生类构造函数的作用
派生类构造函数用于初始化派生类对象,包括调用基类构造函数 和执行派生类特有的初始化操作。
派生类构造函数的执行顺序
派生类构造函数的执行顺序是在创建派生类对象时,先调用基类构 造函数,然后执行派生类构造函数体中的代码。
派生类构造函数的参数
继承和派生共同实现 了面向对象编程中的 代码复用和多态性。
派生是继承的一种表 现形式,通过派生可 以创建新的类。
02
继承的方式
公有继承
总结词
公有继承是ቤተ መጻሕፍቲ ባይዱ基类的公有成员在派生类中仍为公有成员,可以被派生类和派生类的对象访问。
详细描述
公有继承时,基类的公有成员在派生类中保持公有属性,派生类可以访问基类的公有和保护成员。这种继承方式 使得基类的公有成员成为派生类的公有成员,可以被派生类和派生类的对象直接访问,因此派生类可以继承基类 的公有成员函数和变量。
第8章_继承和派生

};
派生类中含有对象成员时,其构造函数的声明格式如下:
派生类的构造函数名称(参数表): 基类的构造函数名(参数表),
对象成员名1(参数表),…对象成员名N(参数表)
{
//…
//派生类构造函数体
}
class Circle2 :public Point
{
double radius;
Point P1; //基类Point的对象成员P1
{
protected
}; void main() { son sonobj;
sonobj.get(); }
8.3 派生类的构造函数和析构函数
派生类的构造函数名称(参数表):基类的构造函数名(参数表) {
… }
class Point
{ int x,y;
public:
Point(int a,int b) //基类的构造函数
Circle (double r,int a,int b):Point(a,b)
//派生类的构造函数
{ radius =r;
cout<<”Constructing Circle class \n”;
}
~ Circle () //派生类的析构函数
{ cout<<”Destructing Circle class \n”; }
使用protected声明的称为保护成员。任何一个类的保护成员 仅可以被其自己和派生类的所有非静态成员函数和友元函数直 接访问,也就是说其他的外部函数是不能访问它的。因此,对 于那些既要对外界隐藏,又要能被派生类访问的成员,可以将 它们声明为保护成员。
8.2.3三种派生方式的定义
class 派生类名 : 派生存取说明符 基类名 { //派生类新增的数据成员和成员函数 }; 1.私有(private)派生
《继承性和派生性》PPT课件

继承方式: public private
protected 直接继承
(P)
6
8.1.2 派生类的三种继承方式(续)
表:继承对基类成员的访问能力
公有继承 私有继承 保护继承
J PHV J PHV J PHV
私有 成员
公有 成员
√√√√√√ (私)
√√ (保)
√
保护 成员
√
√
√
(私)
√
√
精选课件ppt
<派生类新定义成员> };
2、多继承
class <派生类名>:<继承方式1> <基类名1>, <继承方式2> <基类名2>...
{ <派生类新定义成员>
};
精选课件ppt
3
8.1.1 派生类的定义格式(续)
3、继承方式 public:公有继承;
private:私有继承;
protected:保护继承; 作用:控制基类中声明的成员在多大的范围内 能被派生类的用户访问;
7
8.1.2 派生类的三种继承方式(续)
说明: 私有成员不参与继承的访问控制;
基类实例(J):与继承方式无关,遵循访问控制 权限的定义;
直接继承(P):可以访问基类中的公有成员和 保护成员,但成员的权限随继承方式而改变;
水平访问(H)=P+J;
垂直访问(V)=P+P;
保护成员:在垂直访问(V)时相当于公有成员, 在水平访问(H)时相当于私有成员;
14
8.1.2 派生类的三种继承方式(续)
{ Location::Move(xOff,yOff); }
int GetX() {return Location::GetX();}
第08章 继承与派生

作业
教材P270-1.填空题之(1)至(6)
有派生时”改为“ (4)之 注:(4)之“当私有派生时”改为“当公有派生 时”
类名(形参总表):基类1名(实参表),…,成员变量1名(实参表),…{…}
各个构造函数的调用次序是:首先按照类定义中基类的次 序,调用各个基类的构造函数,其次按照类定义中成员的 次序,调用各个成员的构造函数,最后执行派生类构造函 数中的代码。析构函数的调用次数与之相反(见示例程序)
类型兼容
类型兼容是指在公有继承的情况下,一个派生类 对象可以作为基类的对象来访问。类型兼容有三 种使用场景:
手脑并用
做到“上机、上机、再上机”
切忌浮躁
如果你愿意利用5年时间来成为高手,那么你只要两 三年就会成为高手,如果你想一年就成为高手,那 么你5年也成不了高手
继承/派生概述
现实世界中的许多事物,它们之间具有“一般与特殊” 的关系。例如:人是一个群体,学生也是一个群体,某 个具体的学生,他/她既具有人的特征也具有学生的特征 在面向对象的程序设计中, “一般与特殊”的关系使用 继承/派生机制实现,该机制利用已有的“一般”类来定 义新的“特殊”类,使得新类不仅拥有自己的属性和操 作,而且也拥有原有类的属性和操作,实现了代码级别 上的复用 原有类称为基类(Base Class)或父类(Super Class),新 类称为派生类(Derived class)或子类(Sub Class) 子类拥有父类属性和操作这一过程称为继承(Inherit); 由父类产生子类的过程称为派生(Derive)
《继承和派生》课件

派生类的析构函数
派生类析构函数在销毁派生类对象时 自动调用,用于释放派生类所占用的 资源。
派生类析构函数可以包含代码,用于 清理派生类所占用的资源。
派生类析构函数可以访问基类的析构 函数,通过使用`this`关键字调用基类 析构函数。
派生类析构函数可以重载基类析构函 数,以便在销毁派生类对象时执行特 定的操作。
基类析构函数的调用
在派生类的析构函数中,可以通过使用`this`关键字调 用基类的析构函数,以确保基类资源得到正确释放。
输标02入题
如果在派生类的析构函数中没有显式调用基类的析构 函数,则编译器会自动调用基类的默认析构函数。
01
03
在某些情况下,可能需要显式调用基类的析构函数, 以确保资源得到正确释放。例如,当基类包含动态分
02 继承的方式
公有继承
总结词
公有继承是指子类可以访问父类的公有成员。
详细描述
在公有继承中,子类可以访问父类的公有成员(即不加任 何修饰符的成员),这些成员在子类中保持公有属性。子 类可以继承和使用父类的公有成员,包括函数、变量、常 量等。
总结词
公有继承是实现代码复用的一种方式。
详细描述
通过公有继承,子类可以继承父类的公有成员,从而避免 重复编写相同的代码。这有助于提高代码的复用性和维护 性。
注意事项
虚函数和纯虚函数的使用 应合理规划,避免过度使 用导致程序复杂度和维护 成本增加。
继承和派生的效率问题
继承
通过共享已存在的代码, 减少代码冗余。但也可能 导致内存浪费和性能下降 。
派生
通过扩展已有类,增加新 功能或修改已有功能。但 也可能导致内存消耗增加 和性能下降。
注意事项
继承与派生

Empolyee(类名)
属性
ProgrammerClass(类名)
属性
+name:string + sex:string + heigh:double
+name:string + sex:string + heigh:double +language:string +datebase:string
服务(动作) 输入信息 显示信息
作业
• 定义一个日期类,继承自时钟类,新增年月日 属性,完善输入与输出方法.
总结
1、面向对象的继承机制; 重用现有类去创建新类的特性. 2、面向对象继承的实现; 利用[类的修饰符]class 类名:基类名 {} 注意:构造函数与析构函数不被继承 3、隐藏和访问基类的成员。 利用base关键字访问基类的成员,利用 sealed 密封类,利用new隐藏基类的成员.
class ProgrammerClass:EmployeeClass { private string language; private string databases; public ProgrammerClass():base()//引用基类的构造函数 public void AcceptSkillSet() {base.AcceptDetails ();//调用基类的方法 Console.WriteLine ("请输入所掌握的编程语言"); language=Console.ReadLine (); Console.WriteLine ("请输入所掌握的数据库"); databases=Console.ReadLine ();} public void DisplaySkillSet() {base.DisplayDetails ();//调用基类的方法 Console.WriteLine ("{0}所掌握的编程语言{1}", ,nguage ); Console.WriteLine ("{0}所掌握的数据库是{1}", ,this.databases );} }
第八讲 继承与派生总结

第8讲 继承与派生在C++中所谓“继承”就是在一个已存在的类的基础上建立一个新的类。
已存在的类称为“基类(base class)”或“父类(father class)”。
新建立的类称为“派生类(derived class)”或“子类(son class)”。
1.类的继承与派生派生类是在基类的基础上产生的特殊类,派生类自动继承了基类的成员。
派生类具有自身的属性和行为,不然就完全等同于基类,这样就没有必要派生新类。
继承是为了避免代码的重复继承是为了避免代码的重复派生是为了使新产生的派生类除具有基类的共性之外,还具有其他个性。
设计两个类,一个类描述点,另一个类描述圆。
圆由圆心和半径构成,圆类由点类派生而来,其中圆心的特性由点类继承下来。
#include "iostream.h"class Point{int m_x,m_y;public:Point(int x,int y){m_x=x;m_y=y;}int get_x(){return m_x;}int get_y(){return m_y;}};class Circle:public Point { 描述点的类的设计: ①数据成员 点的坐标值(x,y) ②成员函数 根据需要定义。
如构造函数、取值函数、设值函数 Public 继承double radius;public:Circle(int x,int y,double r):Point(x,y){radius=r;}double Area(void){return 3.14*radius*radius;}int get_centreX(){return get_x();}int get_centreY(){return get_y();}};void main(){int x,y;double r;cout<<"x=";cin>>x;cout<<"y=";cin>>y;cout<<"r=";cin>>r;Circle c(x,y,r);cout<<"the centre of the Circle is the point("<<c.get_centreX()<<","<<c.get_centreY()<<")"<<endl;cout<<"the Area of the Circle is "<<c.Area()<<endl;}1.3 派生类的生成过程①吸收基类成员 派生类吸收基类中除构造函数和析构函数之外的全部成员②改造基类成员③添加派生类新成员2 访问权限控制(1)先由继承方式决定,再看基类成员的访问权限3 类型兼容规则(1)类型兼容规则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
调用多个基类的同名函数造成的二义性问题 class A { public: F(); ...... }; class B { public: F(); ...... }; class C:public A,public B { ...... }; void main() { C obj; obj.F(); //错误,产生二义 错误, 错误 //用域限定符消除二义性 用域限定符消除二义性 obj.A::F(); obj.B::F(); }
#include "Derived.h" void main() { CDerived ob(10,20); ob.show(); //ob.ShowBase(); 出错本函数在派生类中为私有成员 } //// recderived.h //#include <iostream.h> //#include "derived.h“ //class reCDerived :public CDerived{ //public: // void showc(){ShowBase();show();cout<<"c="<<c<<endl;} // reCDerived(int x=0,int y=0,int z=0):CDerived(x,y){c=z;} //private: // int c; //};
继承方式: 继承方式: class person{ private: ...... protected: //在类的内部、友员和派生类中被访问 在类的内部、 在类的内部 ...... public://在类的内部、友员、派生类和类的外部被访问 在类的内部、友员、 在类的内部 ...... }; //基类 基类 class student : public person{......}; //公有派生 公有派生 class student : private person{......}; //私有派生 私有派生 //仅在类的内部和友员中被访问 仅在类的内部和友员中被访问
类 成 员 的 访 问 控 制
继承方式
不同继承方式的影响主要体现在:
1、派生类成员 成员对基类成员的访问控制。 成员 2、派生类对象 对象对基类成员的访问控制。 对象
三种继承方式
公有继承 私有继承 保护继承
派生特点 (1)无论哪种派生方式基类的私有成员在派生类中都不可见, )无论哪种派生方式基类的私有成员在派生类中都不可见, 不可访问。 不可访问。 (2)公有派生,基类中的保护成员和公有成员在派生类中的访 )公有派生, 问特性不变。 问特性不变。 (3)私有派生,基类中的保护成员和公有成员在派生类中变成 )私有派生, 私有成员。 私有成员。 (4)保护派生,基类中的保护成员和公有成员在派生类中变成保 保护派生, 保护派生 护成员。 护成员。
第八章 继承
保持已有类的特性而构造新类的过程称为继承。 在已有类的基础上新增自己的特性而产生新类的过程称为派生。 被继承的已有类称为基类(或父类)。 派生出的新类称为派生类。 继承:在既有的类的基础上创建新的类,新类可以从一个或多个类中继承函数和数据, 继承:在既有的类的基础上创建新的类,新类可以从一个或多个类中继承函数和数据,并 可以重新定义或添加新的数据和函数。 可以重新定义或添加新的数据和函数。
保护继承(protected)
类 成 员 的 访 问 控 制
基类的public和protected成员都以 protected身份出现在派生类中,但基 类的private成员不可访问。 派生类中的成员函数可以直接访问基类 中的public和protected成员,但不能访 问基类的private成员。 通过派生类的对象不能访问基类中的任 何成员
虚基类 base base1 base2
class base { private: int a; public:
derived
base(int x) {a=x;} ...... };
class base1:public base { public: base1(int x):base(x) {} }; class base2:public base { public: base2(int x):base(x) {} }; class derived: public base1, public base2 { public:
多层次继承
class cls1{ private: int a; ...... public: cls1(int x) {a=x;} ...... }; class cls2:public cls1{ private: int b; ...... public: cls2(int x,int y):cls1(y) {b=x;} ...... };
// Derived.h #include "Base1.h" class CDerived :public CBase{ public: void show(); int GetB(); void SetB(int); CDerived(int=0,int=0); prs A{ public: A(int); ...... }; class B{ public: B(float); ...... };
class C:public A,private B { private: int age; public: C(int x,float y,int z):A(x),B(y) { age=z;} ...... };
公有继承示例 // Base1.h class CBase { public: void ShowBase(); int GetA(); void SetA(int); CBase(int x=0); private: int a; };
#include <iostream.h> #include "Base1.h" CBase::CBase(int x) {a=x;} void CBase::SetA(int x) {a=x;} int CBase::GetA() {return a;} void CBase::ShowBase() { cout<<"a="<<a<<endl;}
多层次继承中的构造函数和析构函数执行顺序
类1 类2 类3 类4 类5 构造函数 执行顺序 析构函数 执行顺序
•多重继承 多重继承 是指一个派生类具有多个父类。 是指一个派生类具有多个父类。
车类 玩具类
玩具车类 class A{......}; class B{......}; class C:public A,private B{......};
•使用虚基类示例: 使用虚基类示例: 使用虚基类示例
class base { private: int a; public: base(int x) {a=x;} ...... };
class base1: virtual public base { public: base1(int x):base(x) {} }; class base2: virtual public base { public: base2(int x):base(x) {} };
私有继承(private)
类 成 员 的 访 问 控 制
基类的public和protected成员都以 private身份出现在派生类中,但基类的 private成员不可访问。 派生类中的成员函数可以直接访问基类 中的public和protected成员,但不能访 问基类的private成员。 通过派生类的对象不能访问基类中的任 何成员。
汽车
运输汽车
专用汽车
客车
货车
消防车
洒水车
为什么要继承 (1)代码复用 ) (2)保持代码的一致性 ) (3)易维护性 ) (4)易扩展性 ) (5)提供问题的层次性解决方案 )
保护成员的引入 class student{ private: ...... protected: ...... public: ...... }; 保护成员为类的继承而设计,它在类的内部和派 生类中可以访问,在类的外部不可访问。
class derived: public base1, public base2 { public: derived(int x,int y): base(x),base1(x),base2(y) {} }; void main() { derived obj(10,20); }
总结: 总结:当有类似下图所 示的继承方式的情况时, 示的继承方式的情况时, 会造成构造base类的二 会造成构造 类的二 义性。 义性。为解决此问题引 入虚基类, 入虚基类,由derived 类直接构造base类以消 类直接构造 类以消 除二义性。 除二义性。
#include "Derived.h" #include <iostream.h> CDerived::CDerived(int x,int y):CBase(y) {b=x;} void CDerived::SetB(int x) {b=x;} int CDerived::GetB() {return b;} void CDerived::show() { ShowBase(); cout<<"b="<<b<<endl;}
derived(int x,int y): base1(x),base2(y) {} }; void main() { derived obj(10,20); } 二义性问题: 二义性问题:类base中的数据成 中的数据成 被初始化为10还是 员a被初始化为 还是 被初始化为 还是20? 解决方案: 解决方案:将base1和base2设 和 设 为虚基类,用类derived直接构 为虚基类,用类 直接构 造类base,这样保证了base类 造类 ,这样保证了 类 的构造的唯一性。 的构造的唯一性。