第5章 继承与派生

合集下载

第5章 继承与派生-Qt C++跨平台图形界面程序设计基础(第2版)-殷立峰-清华大学出版社

第5章 继承与派生-Qt C++跨平台图形界面程序设计基础(第2版)-殷立峰-清华大学出版社

protected:
};
string name;
int age;
char sex;
};
class Person{
class Employee: public Person {
public:
public:
void print( ) {
cout<<“name:”<<name<<endl; cout<<“age:”<<age<<endl;
cout<<"salary="<<salary<<endl; } ~Employee() { delete []name; } private: char *name; short age; float salary; };
//定义派生类Manager class Manager: public Employee { public:
void set_level(int l=0) {
level = l; } void Print_level() {
cout<<"level:"<<level<<endl; }
int main() {
Employee e("lihua",30,3000); e.Print(); Manager m; m.set_level(1); m.Print();
{
<<endl;
cout<<“name:”<<name<<endl; cout<<“age:”<<age<<endl; cout<<“sex:”<<sex<<endl; }

《C++面向对象程序设计》_第5章 继承和派生

《C++面向对象程序设计》_第5章 继承和派生

基类名
《C++面向对象程序设计》, 李晋江, 清华大学出版社
构造一个派生类包括以下3部分工作 : (1) 从基类接收成员。派生类把基类全部的成员(不包括构造函数和析 构函数)接收过来,也就是说是没有选择的,不能选择接收其中一 部分成员,而舍弃另一部分成员。 (2) 处理从基类接收的成员。接收基类成员是程序人员不能选择的, 但是程序人员可以对这些成员作某些处理。 (3) 在声明派生类时增加的成员。这部分内容是很重要的,它体现了 派生类对基类功能的扩展。要根据需要仔细考虑应当增加哪些成
}
《C++面向对象程序设计》, 李晋江, 清华大学出版社
• 只有公用派生类才是基类真正的子类型,它完整地继承了基类的 功能。基类与派生类对象之间有赋值兼容关系,由于派生类中包 含从基类继承的成员,因此可以将派生类的值赋给基类对象,在 用到基类对象的时候可以用其派生类对象代替。赋值兼容存在以 下三种形式: (1)派生类对象可以向基类对象赋值; (2)派生类对象可以替代基类对象向基类对象的引用进行赋值或初 始化; (3)派生类对象的地址可以赋给指向基类对象的指针变量,也就是 说,指向基类对象的指针变量也可以指向派生类对象。 • 赋值兼容仅是针对public派生,如果派生方式是private或protected, 则上述三条不可行。
class Student : public Person { … };
void eat(Person &p){}; void study(Student &s){}; void main( ) { Person p; Student s; eat(p); // OK eat(s); // OK 学生也要吃饭 study(s); // OK study(p); // error C2664: ―study‖: 不能将参数 1 从“Person‖转换为“Student &‖

第5章 继承和派生类

第5章 继承和派生类
19
对类B的对象初始化即是对x,y,z,m,n等全部成员的初始化
5.4.2 私有继承
私有派生,派生类中基类的公有和保 护成员成为私有
class ClassName : private BaseClassName
私有派生时,基类中公有成员和保护成员在派生类 中均变为私有,在派生类中仍可直接使用这些成员,基 类中的私有成员,在派生类中不可直接使用。
15
从一个基类派生一个类的一般格式为:
class ClassName : <Access> BaseClassName
{ private: public:
派生类名 继承方式 基类名
......; //私有成员说明
......; //公有成员说明
protected:
派生类中新增加的成员
......; //保护成员说明
C++程序设计
主讲:王新祥
第5章 继承和派生类
2
5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9
继承与派生的概念 派生类的声明方式 派生类的构成 派生类成员的访问属性 派生类的构造函数和析构函数 多重继承 基类与派生类的转换 继承与组合 继承在软件开发中的重要意义
3
继承性是面向对象程序设计中最重要的机制。这 种机制提供了无限重复利用程序资源的一种途径。通 过C++语言中的继承机制,可以扩充和完善旧的程序 以适应新的需求。这样不仅可以节省程序开发的时间 和资源,并且为将来的程序增添了新的资源。
基类:public: 在派生类和类外都可以使用 protected: 在派生类中使用 private: 不能在派生类中使用
17
class A { int x; 因为y是基类保护,所以在派生类中可以 protected: int y; 直接引用。而在类外不可直接引用。 public: int z; A(int a, int b, int c) { x=a; y=b; z=c; } //基类初始化 int Getx() { return x; } //返回x int Gety() { return y; } //返回y void ShowA() { cout<< "x="<<x<<'\t'<<"y="<<y<<'\t'<<"z="<<z<<'\n'; } }; 因为z是基类公有,所以 公有派生 class B : public A { 在 派 生类 中和 类 外均 可 对基类初始化 int m, n; 直接引用。 public: B(int a, int b, int c, int d, int e) : A(a, b, c) { m=d; n=e; } void Show() { cout<<"m="<<m<<'\t'<<"n="<<n<<'\n'; cout<<"x="<<Getx()<<'\t'<<"y="<<y<<'\t'<<"z="<<z<<'\n'; } int Sum() { return (Getx()+y+z+m+n); } }; 因为x是基类私有,所以在派生类中和类外不能直接引用 void main(void) { B b1(1, 2, 3, 4, 5); b1.ShowA(); b1.Show(); cout<<"Sum="<<b1.Sum()<<'\n';cout<<"x="<<b1.Getx()<<'\t'; cout<<"y="<<b1.Gety()<<'\t'; cout<< "z="<<b1.z<<'\n'; } 18

C++第5章习题参考答案

C++第5章习题参考答案

1.什么是类的继承与派生?继承性是面向对象程序设计的第二个重要特性,通过继承实现了数据抽象基础上的代码重用。

继承是对许多问题中分层特性的一种自然描述,因而也是类的具体化和被重新利用的一种手段,它所表达的就是一种对象类之间的相交关系。

它使得某类对象可以继承另外一类对象的特征和能力。

继承所具有的作用有两个方面:一方面可以减少代码冗余;另一方面可以通过协调性来减少相互之间的接口和界面。

通过继承方式定义的子类也称为派生类。

2.类的三种继承方式之间的区别是什么?类的继承方式有public(公有)继承、protected(保护)继承和private(私有)继承三种。

对于不同的继承方式,会导致基类成员原来的访问属性在派生类中有所变化。

表5.1列出了不同继承方式下基类成员访问属性的变化情况。

表5.1 不同继承方式下基类成员的访问属性说明:该表第1列给出3种继承方式,第1行给出基类成员的3种访问属性。

其余单元格内容为基类成员在派生类中的访问属性。

从表中可以看出:(1) 基类的私有成员在派生类中均是不可访问的,它只能由基类的成员访问。

(2) 在公有继承方式下,基类中的公有成员和保护成员在派生类中的访问属性不变。

(3) 在保护继承方式下,基类中的公有成员和保护成员在派生类中均为保护的。

(4) 在私有继承方式下,基类中的公有成员和保护成员在派生类中均为私有的。

需要注意的是:保护成员与私有成员唯一的不同是当发生派生后,处在基类protected区的成员可被派生类直接访问,而私有成员在派生类中是不可访问的。

在同一类中私有成员和保护成员的用法完全一样。

3.派生类能否直接访问基类的私有成员?若否,应如何实现?派生类不能直接访问基类的私有成员。

具体实现方式:(1) 在类定义体中增加保护段为了便于派生类的访问,可以将基类私有成员中需提供给派生类访问的部分定义为保护段成员。

保护段成员可以被它的派生类访问,但是对于外界是隐藏起来的。

这样,既方便了派生类的访问,又禁止外界对它的派生类访问。

《继承与派生 》课件

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

第5章继承与派生

第5章继承与派生

第 5 章继承与派生5.1 继承与派生的看法图图图图25.2 派生类的声明方式5.3 派生类的构成数据构造 (C++版 )图图5.4 派生类成员的接见属性5.4.1 公用继承C++ 面向对象程序设计3 5.4.2 私有继承图5.4.3 保护成员和保护继承图4数据构造 (C++版 ) 5.4.4 多级派生时的接见属性图5.5 派生类的构造函数和析构函数5.5.1 简单的派生类的构造函数图图5.5.2 有子对象的派生类的构造函数C++ 面向对象程序设计5图5.5.3 多层派生时的构造函数图5.5.4 派生类构造函数的特别形式5.5.5 派生类的析构函数5.6 多重继承5.6.1 声明多重继承的方法5.6.2 多重继承派生类的构造函数5.6.3 多重继承引起的二义性问题6数据构造 (C++版 )图图图图图C++ 面向对象程序设计7图图5. 205.6.4 虚基类1.虚基类的作用图8数据构造 (C++版 )图图图2.虚基类的初始化C++ 面向对象程序设计9图3.虚基类的简单应用举例5.7 基类与派生类的变换图图10数据构造 (C++版 )5.8 继承与组合5.9 继承在软件开发中的重要意义习题1.将例 5.1 的程序片段补充和改写成一个圆满、正确的程序,用公用继承方式。

在程序中应包括输入数据的函数,在程序运行时输入num,name,sex,age,addr的值,程序应输出以上 5 个数据的值。

2.将例 5.2 的程序片段补充和改写成一个圆满、正确的程序,用私有继承方式。

在程序中应包括输入数据的函数,在程序运行时输入num,name,sex,age,addr的值,程序应输出以上 5 个数据的值。

3.将例 5.3 的程序更正、补充,写成一个圆满、正确的程序,用保护继承方式。

在程序中应包括输入数据的函数。

4.更正例5.3 的程序,改为用公用继承方式。

上机调试程序,使之能正确运行并获取正确的结果。

对这两种继承方式作比较剖析,考虑在什么情况下二者不能够互相代替。

第5章 继承和派生类

第5章 继承和派生类
面象对象程序设计
2010/9/18
第5章 继承和派生类
程序运行结果: x=4 y=5 l=6 w=8 程序分析: 通过公有继承方式,从BaseClas类得到DerivedClass类。 派生类DerivedClass只有一个基类,所以是单继承。基类 BaseClass定义了两个数据成员,3个成员函数。派生类 DerivedClass定义了两个数据成员,3个成员函数。通过 继承,派生类DerivedClass拥有4个数据成员:x、y、l和 w,6个成员函数:setx ( )、sety ( )、setl ()、setw ( )、 displayxy ( )、displaylw( )。
2010/9/18
面象对象程序设计
第5章 继承和派生类
class Father:private Grandfather //中间类:Grandfather的 公有派生类, //Son的基类 { public: void test() { b1=10; //可以访问,因b1改为private b2=20; //可以访问,因b2改为private b3=30; //不可访问, 因b3改为不可访问 } };
2010/9/18
面象对象程序设计
第5章 继承和派生类
5.1.2 继承的种类
在C++语言中,一个派生类既可以从一个基类派生,也可 以从多个基类派生。从一个基类派生的继承被称为单继承。 单继承形成的类层次是一个倒挂的树,如图5.2所示。从 多个基类派生类的继承被称为多继承。多继承形成的类层 次是一个有向无环图(DAG),如图5.3所示。在图5.2中, 输入设备是基类,从它派生出了3个派生类:键盘类、鼠 标类和扫描仪类。在图5.3中,从教师类和干部类派生出 校长类,即校长类有两个基类。

第5章 派生类与继承

第5章 派生类与继承

void print();
};
print();
};
//定义一个基类 class person{ protected: char name[10]; int age; char sex; public: //…… }; //定义一个派生类 class employee:public person { protected: char department[20]; float salary; public: //…… };
当类的继承方式为私有继承时,基类的public成员和 protected成员被继承后作为派生类的private成员,派生类 的其他成员可以直接访问它们,但是在类外部通过派生类的 对象无法访问。
基类的private成员在私有派生类中是不可直接访问的, 所以无论是派生类成员还是通过派生类的对象,都无法直接 访问从基类继承来的private成员,但是可以通过基类提供 的public成员函数间接访问。 例5.1一个私有继承的例子
由于派生类继承了基类的成员,派生类的构造 函数需要调用基类的构造函数对其中定义于基 类的数据成员进行初始化。 给基类构造函数传递实际参数是通过向派生类 构造函数传递实际参数以及初始化列表来间接 实现传递的。
5.2.1 派生类构造函数和析构函数的执行顺 序 通常情况下,当创建派生类对象时, 首先执行基类的构造函数,随后再执行 派生类的构造函数; 当撤消派生类对象时,则先执行派生 类的析构函数,随后再执行基类的析构 函数。
例5.3 公有继承的访问规则
表5-3 公有继承的访问规则
基类成员 内部访问 对象访问 Private成员 不可访问 不可访问 public成员 可访问 可访问 protected成员 可访问 不可访问
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第5章继承与派生5.1继承与派生的概念
图5.1
图5.2
图5.3
图5.4
2
C++面向对象程序设计
图5.5
5.2派生类的声明方式
5.3派生类的构成
图5.6
5.4派生类成员的访问属性
5.4.1公用继承
C++面向对象程序设计 3 5.4.2私有继承
图5.7
5.4.3保护成员和保护继承
图5.8
4
C++面向对象程序设计5.4.4多级派生时的访问属性
图5.9
5.5派生类的构造函数和析构函数5.5.1简单的派生类的构造函数
图5.10
图5.11
5.5.2有子对象的派生类的构造函数
C++面向对象程序设计 5
图5.12
5.5.3多层派生时的构造函数
图5.13
5.5.4派生类构造函数的特殊形式
5.5.5派生类的析构函数
5.6多重继承
5.6.1声明多重继承的方法
5.6.2多重继承派生类的构造函数
5.6.3多重继承引起的二义性问题
6
C++面向对象程序设计
图5.14
图5.15
图5.16
图5.17
图5.18
C++面向对象程序设计7
图5.19
图5. 20
5.6.4虚基类
1. 虚基类的作用
图5.21
8
C++面向对象程序设计
图5.22
图5.23
图5.24
2. 虚基类的初始化
C++面向对象程序设计9
图5.25
3. 虚基类的简单应用举例
5.7基类与派生类的转换
图5.26
图5.27
10
C++面向对象程序设计
5.8继承与组合
5.9继承在软件开发中的重要意义
习题
1. 将例5.1的程序片段补充和改写成一个完整、正确的程序,用公用继承方式。

在程序中应包括输入数据的函数,在程序运行时输入num,name,sex,age,addr的值,程序应输出以上5个数据的值。

2. 将例5.2的程序片段补充和改写成一个完整、正确的程序,用私有继承方式。

在程序中应包括输入数据的函数,在程序运行时输入num,name,sex,age,addr的值,程序应输出以上5个数据的值。

3. 将例5.3的程序修改、补充,写成一个完整、正确的程序,用保护继承方式。

在程序中应包括输入数据的函数。

4. 修改例
5.3的程序,改为用公用继承方式。

上机调试程序,使之能正确运行并得到正确的结果。

对这两种继承方式作比较分析,考虑在什么情况下二者不能互相代替。

5. 有以下程序结构,请分析访问属性。

class A//A为基类
{public:
void f1( );
int i;
protected:
void f2( );
int j;
private:
int k;
};
class B: public A //B为A的公用派生类
{public:
void f3( );
protected:
int m;
private:
int n;
};
class C: public B //C为B的公用派生类
{public:
void f4( );
private:
int p;
};
int main( )
{A a1; //a1是基类A的对象
B b1; //b1是派生类B的对象
C c1; //c1是派生类C的对象
return 0;
}问:
(1) 在main函数中能否用b1.i,b1.j和b1.k引用派生类B对象b1中基类A的成员?
(2) 派生类B中的成员函数能否调用基类A中的成员函数f1和f2?
(3) 派生类B中的成员函数能否引用基类A中的数据成员i,j,k?
(4) 能否在main函数中用c1.i,c1.j,c1.k,c1.m,c1.n,c1.p引用基类A的成员i,j,k,派生类B的成员m,n,以及派生类C的成员p?
(5) 能否在main函数中用c1.f1(),c1.f2(),c1.f3()和c1.f4()调用f1,f2,f3,f4成员函数?
(6) 派生类C的成员函数f4能否调用基类A中的成员函数f1,f2和派生类中的成员函数f3?
6. 有以下程序结构,请分析所有成员在各类的范围内的访问权限。

class A
{public:
void f1( );
protected:
void f2( );
private:
int i;
};
class B: public A
{public:
void f3( );
int k;
private:
int m;
};
class C: protected B
{public:
void f4( );
protected:
int m;
private:
int n;
};
class D: private C
{public:
void f5( );
protected:
int p;
private:
int q;
};
int main()
{A a1;
B b1;
C c1;
D d1;
7. 有以下程序,请完成下面工作:
①阅读程序,写出运行时输出的结果。

②然后上机运行,验证结果是否正确。

③分析程序执行过程,尤其是调用构造函数的过程。

#include <iostream> using namespace std;
class A
{public:
A( ){a=0;b=0;}
A(int i){a=i;b=0;}
A(int i,int j){a=i;b=j;}
void display( ){cout<<″a=″<<a<<″b=″<<b;} private:
int a;
int b;
};
class B : public A
{public:
B( ){c=0;}
B(int i):A(i){c=0;}
B(int i,int j):A(i,j){c=0;}
B(int i,int j,int k):A(i,j){c=k;}
void display1( )
{display();
cout<<″c=″<<c<<endl;
}
private:
int c;
};
int main( )
{ B b1;
B b2(1);
B b3(1,3);
B b4(1,3,5);
b1.display1( );
b2.display1( );
b3.display1( );
b4.display1( );
return 0;
8. 有以下程序,请完成下面工作:
①阅读程序,写出运行时输出的结果。

②然后上机运行,验证结果是否正确。

③分析程序执行过程,尤其是调用构造函数和析构函数的过程。

#include <iostream> using namespace std;
class A
{public:
A( ){cout<<″constructing A ″<<endl;}
~A( ){cout<<″destructing A ″<<endl;}
};
class B : public A
{public:
B( ){cout<<″constructing B ″<<endl;}
~B( ){cout<<″destructing B ″<<endl;}
};
class C : public B
{public:
C( ){cout<<″constructing C ″<<endl;}
~C( ){cout<<″destructing C ″<<endl;}
};
int main( )
{C c1;
return 0;
9. 分别定义Teacher(教师)类和Cadre(干部)类,采用多重继承方式由这两个类派生出新类Teacher_Cadre(教师兼干部)。

要求:
①在两个基类中都包含姓名、年龄、性别、地址、电话等数据成员。

②在Teacher类中还包含数据成员title(职称),在Cadre类中还包含数据成员post(职务),在Teacher_Cadre类中还包含数据成员wages(工资)。

③对两个基类中的姓名、年龄、性别、地址、电话等数据成员用相同的名字,在引用这些数据成员时,指定作用域。

④在类体中声明成员函数,在类外定义成员函数。

⑤在派生类Teacher_Cadre的成员函数show中调用Teacher类中的display函数,输出姓名、年龄、性别、职称、地址、电话,然后再用cout语句输出职务与工资。

10. 将本章5.8节中的程序片段加以补充完善,成为一个完整的程序。

在程序中使用继承和组合。

在定义Professor类对象prof1时给出所有数据的初值,然后修改prof1的生日数据,最后输出prof1的全部最新数据。

相关文档
最新文档