260 likes | 453 Views
第八章 继承与多态. 网络游戏开发语言基础 ——C++ 程序设计. 第八章 继承与多态. 静态多态的实现 动态多态的实现 纯虚函数与抽象基类. 静态多态的实现 动态多态的实现. 动态多态的实现. 掌握静态多态的实现 掌握动态多态的实现 熟悉纯虚函数与抽象基类的应用. 第八章 继承与多态. 8.2 多态性 8.2.1 多态的含义,实现意义及分类. 多态的含义. 多态( polymorphism )一词最初来源于希腊语 polumorphos ,含义是具有多种形式或形态的现象。
E N D
第八章 继承与多态 网络游戏开发语言基础——C++程序设计
第八章 继承与多态 • 静态多态的实现 • 动态多态的实现 • 纯虚函数与抽象基类 • 静态多态的实现 • 动态多态的实现 • 动态多态的实现 • 掌握静态多态的实现 • 掌握动态多态的实现 • 熟悉纯虚函数与抽象基类的应用
第八章 继承与多态 • 8.2 多态性 • 8.2.1 多态的含义,实现意义及分类 • 多态的含义 多态(polymorphism)一词最初来源于希腊语polumorphos,含义是具有多种形式或形态的现象。 在程序设计领域,一个广泛认可的定义是“一种将不同的特殊行为和单个泛化记号相关联的能力”,这里的泛化记号其实指的就是函数名。
第八章 继承与多态 • 8.2 多态性 • 8.2.1 多态的含义,实现意义及分类 • 多态的意义 C++程序中允许大量的同名函数出现,体现出多态的使用价值。 1)对不同的数据类型,采用相同或是相似的操作时,使用同名函数。 2)在程序运行中,在某个环节要调用对象的一个特定的方法,而不管这个对象是由哪一个类创建的,这些类都支持这种方法。
第八章 继承与多态 • 8.2 多态性 • 8.2.1 多态的含义,实现意义及分类 • 多态的类型 C++程序中,按照实现机制,多态可以分为两种 overloading overriding C++语言程序中允许存在有若干函数,有完全相同的函数原型,却可以有多种多样的相异的函数体。 C++语言允许函数重载和运算符重载,使用同样的函数名和同样的运算符来完成不同的数据处理与操作。
第八章 继承与多态 • 8.2 多态性 • 8.2.2 静态多态的实现方法 函数重载指的是,允许多个不同函数使用同一个函数名,但要求这些同名函数具有不同的参数表(当然,函数体的实现代码通常也不同)。 系统对这种多态性,对同名函数的处理比较简单。在编译过程中就可以确定该函数与程序中的哪一段代码相联系,即在编译时就已确定函数调用语句对应的函数体代码,故称为静态联编(static banding)处理方式。
第八章 继承与多态 • 8.2 多态性 • 8.2.2 静态多态的实现方法 • 示例 void run(int a); void run(float a); run(1); run(1.0);
第八章 继承与多态 • 8.2 多态性 • 8.2.2 动态多态的实现方法 C++语言程序中允许存在有若干函数,有完全相同的函数原型,却可以有多种多样的相异的函数体,这种现象称为函数的覆盖。 在编译阶段,系统是无法判断此次调用应执行哪一段函数代码。只有到了运行过程中执行到此处时,才能临时判断应执行哪一段函数代码,这种处理方式称为动态联编(dynamic banding)。
第八章 继承与多态 • 8.2 多态性 • 8.2.2 动态多态的实现方法 • 1. 虚函数 虚函数是C++语言中的重要概念。虚函数在编程中的灵活使用,可使程序具有更好的结构和可重用性。 virtual 返回类型 函数名 ( 参数表 ){…… }; • 示例 virtual void run(int a) { …… };
第八章 继承与多态 • 8.2 多态性 • 8.2.2 动态多态的实现方法 • 1. 虚函数 虚函数常用于基类与派生类中 class graphelem { //自定义类graphelem,将作为其它图元类的基类 protected: int color; //颜色color public: graphelem(int col) { color=col; } virtual void draw(){ …… };//基类中含有一个虚函数 virtual ~graphelem() { …… }; }; • 基类
第八章 继承与多态 • 8.2 多态性 • 8.2.2 动态多态的实现方法 • 1. 虚函数 虚函数常用于基类与派生类中 class line:public graphelem { //自定义类line,为基类graphelem 的派生类 public: virtual void draw(){ …… }; //虚函数draw,负责画出“line” ... }; class circle:public graphelem { //自定义类circle,为基类graphelem 的派生类 public: virtual void draw(){ …… }; //虚函数draw,负责画“circle” …… }; • 派生类
第八章 继承与多态 • 8.2 多态性 • 8.2.2 动态多态的实现方法 • 1. 虚函数 使用虚函数时,需要注意以下3点 说明某一函数成员为虚函数,方法是在说明前加关键字“virtual”。 派生类中虚函数处的关键字virtual可以省略,但基类处的不可省 调用虚函数时,系统对它将采用动态联编的方式进行处理。
第八章 继承与多态 • 8.2 多态性 • 8.2.2 动态多态的实现方法 • 2. 动态联编的机制 使用动态联编时,确定要调用的函数有两种方式 • 通过类对象 line ln1; circle cir1; triangle tri1; ln1.draw(); cir1.draw(); tri1.draw();
第八章 继承与多态 • 8.2 多态性 • 8.2.2 动态多态的实现方法 • 2. 动态联编的机制 使用动态联编时,确定要调用的函数有两种方式 • 通过指针 graphelem *pObj; line ln1; circle cir1; triangle tri1; pObj=&lin1; pObj->draw(); pObj=&cir1; pObj->draw(); pObj=&tri1; pObj->draw();
第八章 继承与多态 • 8.2 多态性 • 8.2.2 动态多态的实现方法 • 2. 动态联编的机制 动态联编的基本步骤 在编译过程中,扫描到表达式pb->f()时,首先检查f()是否为虚函数(若f()不是虚函数,则按静态联编处理,在编译时必须为f()确定对应的函数体代码); (2)若f()为虚函数,则仅把与f()同原型的虚函数的地址信息等列表待查; (3)在程序运行阶段,当程序执行到表达式pb->f()时,根据指针当前所指向的对象类属,来决定这时的f()应执行哪个类中的哪个f(),从而决定执行哪个函数体。
第八章 继承与多态 • 8.2 多态性 • 8.2.2 动态多态的实现方法 • 2. 动态联编的机制 虚函数的动态联编的实现,主要依赖于下面一些条件: 1)基类CB 可有多个派生类CD1,CD2,……,CDn; 2)CB 类指针pb 可以指向CB 的对象,也可以指向CD1,CD2,……CDn的对象; 3)CB 类和CD1,CD2,……CDn 类可以有同样原型(而函数体各异)的函数成员f()(虚函数); 4)运行着的程序根据查对当前指针pb所指向的对象是属于哪个类的,再决定到底执行哪个f()。
第八章 继承与多态 • 8.2 多态性 • 8.2.2 动态多态的实现方法 • 2. 动态联编的机制 采用虚函数对于程序有益之处在于。 1)可使程序简单易读。 2)它使得程序模块间的独立性加强。 3)增加了程序的易维护性。 4)提高了程序中“信息隐藏”的等级。
第八章 继承与多态 • 8.2 多态性 • 8.2.4 纯虚函数和抽象基类 抽象基类的概念是虚函数概念的自然引申,它是虚函数使用的一个更理想的形式。 virtual函数原型=0; 若在虚函数的原型后加上“=0”字样而替掉函数定义体(没有具体的实现),则这样的虚函数称为纯虚函数。 virtual void print()=0;
第八章 继承与多态 • 8.2 多态性 • 8.2.4 纯虚函数和抽象基类 含有纯虚函数的类称为抽象基类。 抽象基类的设计意义在于: 基类并不是完整的类,它在程序中只起到一种框架的作用,它所包含的是与定积分计算相关的数据成员,和计算定积分的函数成员的格式:函数名,参数表,返回类型等等。
第八章 继承与多态 • 8.2 多态性 • 8.2.4 纯虚函数和抽象基类 class inte_algo { //基类inte_algo protected: …… public: inte_algo (float left, float right, int steps) { //基类构造函数 …… } virtual void integrate(void); //基类中说明了一个虚函数integrate virtual ~inte_algo() {;}; }; • 示例 • 基类
第八章 继承与多态 • 8.2 多态性 • 8.2.4 纯虚函数和抽象基类 class rectangle:public inte_algo { //派生类rectangle public: rectangle(float left,float right, int steps):inte_algo (left,right,steps){} virtual void integrate(void); //虚函数integrate }; • 示例 • 派生类
第八章 继承与多态 • 小结(理论课) 静态多态 动态多态 纯虚函数与抽象基类
第八章 继承与多态 • 小测验 • 选择题(单项选择题) • 1、以下哪些是采用虚函数的好处:( ) • A. 可使程序简单易读 B. 使得程序模块间的独立性加强 • C. 增加了程序的易维护性 D. 提高了程序中“信息隐藏”的等级 • 2、( )是一个在基类中说明的虚函数,它在该基类中没有定义,但要求任何派生类都必须定义自己的版本。 • A.虚析构函数B.虚构造函数 • C.纯虚函数 D.静态成员函数 • 3、带有虚基类的多层派生类构造函数的成员初始化列表中都要列出虚基类的构造函数,这样将对虚基类的子对象初始化的次数是( ) • A.与虚基类下面的派生类个数有关 B.多次 • C.二次 D.一次
第八章 继承与多态 • 小测验 • 选择题(不定项选择题) • 1、以下哪些是采用虚函数的好处:( ACD ) • A. 可使程序简单易读 B. 使得程序模块间的独立性加强 • C. 增加了程序的易维护性 D. 提高了程序中“信息隐藏”的等级 • 2、( C )是一个在基类中说明的虚函数,它在该基类中没有定义,但要求任何派生类都必须定义自己的版本。 • A.虚析构函数B.虚构造函数 • C.纯虚函数 D.静态成员函数 • 3、带有虚基类的多层派生类构造函数的成员初始化列表中都要列出虚基类的构造函数,这样将对虚基类的子对象初始化的次数是( D ) • A.与虚基类下面的派生类个数有关 B.多次 • C.二次 D.一次
第八章 继承与多态 • 课后作业 【作业1】设计一个日期类Date,包括年、月、日等私有数据成员。要求实现日期的基本运算,如一日期加上天数、一日期减去天数、两日期相差的天数等。 思路分析:在Date类中设计如下重载运算符函数: Date operator+(int days); 返回一日期加天数得到的日期 Date operator-(int days); 返回一日期减去天数得到的日期 int operator-(Date &b); 返回两日期相差的天数 在实现这些重载运算符函数调用以下私有成员函数: leap(int); 判断指定的年份是否为闰年 dton(Date &); 将指定日期转换为从0年0月0日起的天数 ntod(int); 将指定的0年0月0日起的天数转换为对应的日期
第八章 继承与多态 The End