C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计
“ 目录 C++语言程序设计 基本知识 编程技能 刨根问底 继承的概念 基类和派生类 派生类的构造和析构 同名覆盖与重载 多继承 同名覆盖与重载 转换与继承 在主函数中增加调试信息 C++语言程序设计
基本知识 a C++语言程序设计
8.2 定义基类和派生类 定义派生类时要声明继承方式 ,基类的成员被继承到派生类,访问控制受继承方式的影响 继承导致一种特殊的语法现象:同名覆盖。 三种继承方式 public、protected、private 不同继承方式的影响主要体现在: 派生类 成员 对基类成员的访问控制 派生类 对象 对基类成员的访问控制 C++语言程序设计
8.2 定义基类和派生类 问题:想在屏幕上画出正三角形、矩形或圆形 方法一:结构化方法 方法二:面向对象方法 C++语言程序设计 DrawTri (int x, int y, char color, int side); DrawRect (int x, int y, char color, int length, int width) DrawCircle(int x, int y, char color, int Radius) 方法二:面向对象方法 class circle 圆形 class rectangle 矩形 class triangle 三角形 基类: class shape 色彩 color 位置 (x, y) 泛 化 ? shape circle rectangle triangle C++语言程序设计
8.2 定义基类和派生类 C++语言程序设计 //TShape01.h: 类TShape的头文件 typedef unsigned int uint; class TShape{ private: uint _x, _y; //几何形状的位置 public: TShape(); uint getX(); uint getY(); void setX(uint x); void setY(uint y); void Draw(); }; //TShape01.cpp: 类TShape的实现 #include "TShape01.h" #include <iostream> using namespace std; TShape::TShape(){ _x = 10; _y = 10; } void TShape::Draw(){ cout<<"This is TShape::Draw()"<<endl; 成员函数的分类 构造函数 设置属性值 读取属性值 执行 C++语言程序设计
8.2 定义基类和派生类 C++语言程序设计 //TEllipse01.h: 类TEllipse的头文件 #include "TShape01.h" class TEllipse: public TShape { public: void Draw(); }; // TEllipse01.cpp: 类TEllipse的实现 #include "TEllipse01.h" #include <iostream> using namespace std; void TEllipse::Draw(){ cout<<"Draw an ellipse with color"<<endl; } 成员函数的分类 构造函数 设置属性值 读取属性值 执行 C++语言程序设计
8.2 定义基类和派生类 C++语言程序设计 //Main01.cpp #include " TEllipse01.h" #include <iostream> using namespace std; int main(){ TEllipse m_TEllipse; cout<<"X="<<m_TEllipse.getX()<<", Y=" <<m_TEllipse.getY()<<endl; //显示默认的x、y值 m_TEllipse.setX(11u); //修改x的值 //m_TEllipse._y = 21u; //错误!用户代码不能通过类的 对象访问私有成员 m_TEllipse.setY(21u); //修改y的值 <<m_TEllipse.getY()<<endl; //显示修改后的x、y值 m_TEllipse.Draw(); return 0; } 程序运行结果: X=10, Y=10 X=11, Y=21 Draw an ellipse with color C++语言程序设计
8.2 定义基类和派生类 派生类定义的语法格式是: class 派生类名 : 继承方式 基类1, 继承方式 基类2, …, 继承方式 基类n { 派生类成员声明; }; 例如: 已有基类b1和b2,定义派生类derive,其中包括私有整型成员 newInt,公有函数成员 int newFun(),私有函数成员 int max(int a, int b);写出类derive的定义。 class derive : public b1 , private b2 { private: int newInt; public: void newFun(); int max( int a, int b ); };
8.2 定义基类和派生类 类成员的可见性 继承的方式 派生类继承了基类中的所有成员,但不包括 C++语言程序设计 公共成员:public 保护成员:protected 私有成员:private 继承的方式 公有继承(public) 保护继承(protected) 私有继承(private) 派生类继承了基类中的所有成员,但不包括 构造函数 析构函数 默认赋值运算符 C++语言程序设计
8.2 定义基类和派生类 C++语言程序设计 不同继承方式决定的不同访问控制权限体现在: 派生类的成员函数对其继承的基类成员的访问控制; 其它模块通过派生类对象对其继承的基类成员的访问控制。 继承来的成员 的访问权限? public protected private 继承方式决定继承 成员的访问权限 private: protected: public: 基类 ? 派生类 C++语言程序设计
8.2 定义基类和派生类 1. 公有继承 C++语言程序设计 派生类成员 函数可以访问 公有继承的派生类定义形式: class 派生类名:public 基类名 { 派生类新成员定义; }; private: protected: public: 基类 ? 派生类 基类 成员的 属性 public private protected public 派生类对象 基类成员 在派生类中的访问属性不变。 派生类的成员函数 可以访问基类的公有成员和保护成员,不能访问基类的私有成员; 派生类以外的其它函数 可以通过派生类的对象,访问从基类继承的公有成员, 但不能访问从基类继承的保护成员和私有成员。 C++语言程序设计
8.2 定义基类和派生类 2. 私有继承 C++语言程序设计 派生类成员 函数可以访问 私有继承的派生类定义形式: class 派生类名:private 基类名 { 派生类新成员定义; }; 派生类对象 private: protected: public: 基类 ? 派生类 基类 成员的 属性 private private 基类成员 在派生类中的访问属性都变成 private。 派生类的成员函数 可以访问基类的公有成员和保护成员,不能访问基类的私有成员; 派生类以外的其它函数 不能通过派生类的对象,访问从基类继承的任何成员。 C++语言程序设计
8.2 定义基类和派生类 C++语言程序设计 私有继承和保护继承的区别 孙类成员函数无法访问 private: protected: public: 父类 private private: 子类 private private: 孙类 private protected public private 孙类成员函数可以访问 private: protected: public: 父类 private protected 子类 private protected 孙类 protected public protected C++语言程序设计
8.2 定义基类和派生类 C++语言程序设计 继承方式影响访问控制 public: protected: private: public 基类存取方式 继承类型 派生类继承的基类成员的访问属性 public: protected: private: public protected private C++语言程序设计
8.2 定义基类和派生类 C++语言程序设计 同名覆盖(Override): 派生类修改基类的成员,是在派生类中声明了一个与基类成员同名的新成员。 在派生类作用域内或者在类外通过派生类的对象直接使用这个成员名,只能访问到派生类中声明的同名新成员,这个新成员覆盖了从基类继承的同名成员,这种情况称为同名覆盖。 class base { public: void f () {cout<<"base"<<endl;} }; class deriver: public base { void f () {cout<<"deriver"<<endl;} int main( ) { deriver derobj; derobj.f (); return 0; } 在派生类中声明了一个与基类成员同名的新成员 OverRide 在派生类作用域内或者 在类外通过派生类的对 象直接使用这个成员名 输出结果? A: base B: deriver 只能访问到派生类中的同名新成员 C++语言程序设计