第11讲 类的继承 1. 类的继承的概念 2. 类的单继承机制 3. 单继承中的构造函数和析构函数
学习目标 理解类的继承的概念,掌握基类和派生类的定义 掌握三种继承方式下基类不同成员在派生类中访 问权限的变化和基类私有成员在派生类中的调用 方法 掌握两种情况下的构造函数和析构函数的调用
第10讲 类的继承 1. 类的继承的概念 2. 类的单继承机制 3. 单继承中的构造函数和析构函数
类的继承的提出 问题:能否在定义CollegeStudent类时充分利用已有的Student类,而不用重新定义所有成员? class Student { public: void display() cout<<num; cout<<name; } private: int num; //学号 char name[10]; //姓名 }; class CollegeStudent {public: void display() { cout<<num; cout<<name; cout<<speciality; } private: int num; //学号 char name[10]; //姓名 char speciality[5]; //专业 }; 问题:能否在定义CollegeStudent类时充分利用已有的Student类,而不用重新定义所有成员? 4
类的继承的提出 类的继承是面向对象程序设计中最重要的机制。 这种机制提供了无限重复利用程序资源的一种途 径。 类的继承是面向对象程序设计中最重要的机制。 这种机制提供了无限重复利用程序资源的一种途 径。 基于类的继承,可以扩充和完善旧的程序以适应 新的需求。这样不仅可以节省程序开发的时间和 资源,并且为未来程序增添了新的资源。 类的继承,其核心是基于已有的类快速创建新类 的方法。
类的继承—对生物遗传机制的模拟 人类的染色体
继承的多样性与稳定性 我和祖先很相似! 传83代
类的继承的概念 类A派生类B:类A为基类,类B为派生类。 B 派生类 A 基类 基类原有成员数据和成员函数 新增加的成员数据和成员函数
类的继承的概念 在C++语言中,一个派生类可以从一个基类派 生,也可以从多个基类派生。 从一个基类派生的继承称为单继承;从多个基 类派生的继承称为多继承。 在建立派生类的过程中,基类不会做任何改变, 派生类会在基类的基础上发生变化。
第10讲 类的继承 1. 类的继承的概念 2. 类的单继承机制 3. 单继承中的构造函数和析构函数
类的继承的实现 三种派生方式 A 基类 B 派生类 派生并不是简单的扩充,有可能改变基类的性质。 public: 表示公有派生 private:表示私有派生(默认) protected:表示保护派生 派生并不是简单的扩充,有可能改变基类的性质。 有三种派生方式:公有派生、保护派生、私有派生。 默认的是私有派生。
类的继承的实现 class B:public A{...}; class B:protected A{...}; 派生类名 继承方式 基类名 class ClassName:<Access>BaseClassName class B:public A{...}; class B:protected A{...}; class B:private A{...}; class B: A {...}; 默认为私有派生
类的继承的实现 派生类中新增加的成员 派生类名 继承方式 基类名 class ClassName:<Access>BaseClassName { private: ......; //私有成员说明 public: ......; //公有成员说明 protected: ......; //保护成员说明 } 派生类中新增加的成员
公有继承—保持基类成员属性 public A 基类 B 派生类 x y z Fx() Fy() Fz() x y z Fx() Fy() class ClassName: public BaseClassName A 基类 B 派生类 私有 x y z Fx() Fy() Fz() 私私有 x y z Fx() Fy() Fz() 保护 public 保护 公有 公有 基类继承 私有 私私有 保护 保护 公有 公有 私有 m n Fm() Fn() 公有继承时,基类中所有成员在派生类中保持各个成员的访问权限。派生类新增成员不能直接访问基类原私有成员,必须通过继承的基类公有或保护成员来间接访问 公有 派生类新增 私有 公有
调用基类公有成员函数,该函数又调用基类私有成员数据 调用派生类公有成员函数,该函数又调用派生类私有成员数据 公有继承举例 class Student {private: int num; public: void display(){cout<<num;}}; class CollegeStudent:public Student { private: char speciality; public: void display1( ) { cout<<speciality; } }; void main() CollegeStudent s; s.display(); s.display1(); return 0; } 公有成员 派生类中的基类成员函数能够访问派生类中继承的基类私有数据 公有继承 公有新增成员 调用基类公有成员函数,该函数又调用基类私有成员数据 调用派生类公有成员函数,该函数又调用派生类私有成员数据
私有继承时,基类中的公有和保护成员在派生类中均变为私有成员。派生类新增成员不能直接访问基类原私有成员,必须通过继承的基类其他成员来间接访问。 私有继承—基类成员全变成私有 class ClassName: private BaseClassName A 基类 B 派生类 私有 x y z Fx() Fy() Fz() 私私有 x y z Fx() Fy() Fz() 保护 private 私有 公有 私有 基类继承 私有 私私有 保护 私有 公有 私有 私有 m n Fm() Fn() 私有继承时,基类中的公有和保护成员在派生类中均变为私有成员。派生类新增成员不能直接访问基类原私有成员,必须通过继承的基类其他成员来间接访问。 公有 派生类新增 私有 公有
将display()换成cout<<num<<name可以吗 调用派生类公有成员函数,该函数又调用派生类私有成员数据 私有继承举例 display()中调用基类私有数据 class Student {public: void display(){ cout<<num<<name; } private: int num; char name[30]; }; class CollegeStudent:private Student {public: void display1( ) { display(); cout<<speciality; } private: char speciality; void main() { CollegeStudent s; s.display1(); return 0; } 基类私有成员不能由派生类新增函数调用,只能用基类成员函数调用 此处display()是什么属性? 将display()换成cout<<num<<name可以吗 调用派生类公有成员函数,该函数又调用派生类私有成员数据
保护继承—基类成员安全级提升 protected A 基类 B 派生类 x y z Fx() Fy() Fz() x y z Fx() class ClassName: protected BaseClassName A 基类 B 派生类 私有 x y z Fx() Fy() Fz() 私私有 x y z Fx() Fy() Fz() 保护 protected 私有 公有 保护 基类继承 私有 私私有 保护 私有 公有 保护 私有 m n Fm() Fn() 保护继承时,基类中原保护成员在派生类中变为私有成员,基类原公有成员在派生类中变为保护成员。派生类新增成员不能直接访问基类私有成员,必须通过继承的基类其他成员来间接访问。 公有 派生类新增 私有 公有
此处,派生类公有成员函数可以调用name吗? 调用派生类公有成员函数,该函数又调用派生类私有成员数据 保护继承举例 class Student { protected: int num; string name; }; class CollegeStudent:protected Student {public: void display ( ) { cout<<num; cout<<name; } void main() { CollegeStudent s; s.display (); s. name=“Zhang”; return 0; } 基类保护成员在保护派生下变为派生类私有成员,能够被派生类新增成员函数调用 此处,派生类公有成员函数可以调用name吗? 调用派生类公有成员函数,该函数又调用派生类私有成员数据 name为派生类私有,不能在类外调用
不同继承方式 基类成员变量或函数 派生类成员变量或函数 Public继承 Protected继承 Private继承 Public Private Private Protected Private Private Private Private Private Private Private
第10讲 类的继承 1. 类的继承的概念 2. 类的单继承机制 3. 单继承中的构造函数和析构函数
单继承中的构造函数和析构函数 如何初始化? class B { public: B(int bb) { b=bb;} private: int b; }; class C:public B { public: C(int cc){ c=cc; } private: B memB; int c; C int b; //基类数据成员 int c; //新增数据成员 B menB; //内嵌子对象 如何初始化?
(一)简单派生类的构造函数 简单派生类只有一个基类,数据成员中不包括基 类的对象。 简单派生类构造函数的定义形式为: 简单派生类只有一个基类,数据成员中不包括基 类的对象。 简单派生类构造函数的定义形式为: 派生类构造函数(总参数列表): 基类构造函数(参数列表) { 派生类中新增数据成员初始化; } 派生类的总参数类别,不仅能满足派生类新增成员的初始化需要,还要满足基类构造函数中的参数需要。
A(int a,int b,int c){x=a;y=b;z=c;}//基类初始化 int Getx(){return x;} //返回x class A { int x; 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';} }; 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);} 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';} 第一章 VC集成开发环境
定义基类A的对象,调用基类A的成员函数showA(),正确 class A { int x; 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';} }; class B:private 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);} 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';} 私有继承 定义基类A的对象,调用基类A的成员函数showA(),正确 错误 A a1(1,2,3); a1.ShowA(); 错误 第一章 VC集成开发环境 错误 错误
(一)简单派生类的构造函数 构造函数的执行顺序: 析构函数的执行顺序: 基类的构造函数。 派生类的构造函数。 派生类的析构函数。 基类的析构函数。
(二)有子对象的派生类构造函数 class Stu {protected: int num; char name[9]; }; 有子对象的派生类是指:派生类的成员包括基类 的对象。 class Stu {protected: int num; char name[9]; }; class ColStu:public Stu {public: void display( ); private: char speciality; Stu s;
(二)有子对象的派生类构造函数 有子对象的派生类构造函数的一般形式为: 派生类构造函数(总参数列表): 基类构造函数(参 数列表),子对象名(参数列表) { 派生类中新增数据成员初始化; } 派生类的总参数类别,不仅能满足派生类新增成员的初始化需要,还要满足基类构造函数以及子对象构造函数中的参数初始化需要。
class B { private: int b; public: B(int bb) { b=bb; cout<<"B:"<<b<<endl; } }; class C:public B { public: C(int aa,int bb,int cc):B(aa), memB(bb) { c=cc; cout<<"C:"<<c<<endl;} private: B memB; int c; void main() { C c(1,2,3); }
(二)有子对象的派生类构造函数 构造函数的执行顺序: 析构函数的执行顺序: 基类的构造函数。 子对象的构造函数。 派生类的构造函数。 派生类的析构函数。 子对象的析构函数。 基类的析构函数。
第10讲 类的继承 1. 类的继承的概念 2. 类的单继承机制 3. 单继承中的构造函数和析构函数
学习目标 理解类的继承的概念,掌握基类和派生类的定义 掌握三种继承方式下基类不同成员在派生类中访 问权限的变化和基类私有成员在派生类中的调用 方法 掌握两种情况下的构造函数和析构函数的调用 目标层次:理解和记忆 目标层次:分析与综合 目标层次:归纳与扩展
思考: 多个基类来共同派生一个类如何实现? D A 类A成员 类B成员 B 类C成员 C 新增成员