C++程序设计 教学课件 ppt 作者 张桦第7章 面向对象程序设计

上传人:w****i 文档编号:92479063 上传时间:2019-07-10 格式:PPT 页数:147 大小:1.22MB
返回 下载 相关 举报
C++程序设计 教学课件 ppt 作者 张桦第7章 面向对象程序设计_第1页
第1页 / 共147页
C++程序设计 教学课件 ppt 作者 张桦第7章 面向对象程序设计_第2页
第2页 / 共147页
C++程序设计 教学课件 ppt 作者 张桦第7章 面向对象程序设计_第3页
第3页 / 共147页
C++程序设计 教学课件 ppt 作者 张桦第7章 面向对象程序设计_第4页
第4页 / 共147页
C++程序设计 教学课件 ppt 作者 张桦第7章 面向对象程序设计_第5页
第5页 / 共147页
点击查看更多>>
资源描述

《C++程序设计 教学课件 ppt 作者 张桦第7章 面向对象程序设计》由会员分享,可在线阅读,更多相关《C++程序设计 教学课件 ppt 作者 张桦第7章 面向对象程序设计(147页珍藏版)》请在金锄头文库上搜索。

1、C+程序设计,第7章 面向对象程序设计,7.1 基于过程与面向对象的设计思想 7.2 继承 7.3 虚函数 7.4 面向对象程序设计 7.5 面向对象程序设计示例 7.6 本章小结,第7章 面向对象程序设计,游戏准备:猜先、让子等 黑子先走 绘制棋局画面 判断输赢 白棋下子 绘制棋盘画面 判断输赢 返回步骤2 输出棋局结果,7.1 基于过程与面向对象的设计思想,玩家对象:黑白双方,这两方的行为是一模一样的 棋盘对象:负责绘制棋局画面 裁判对象:规则系统,负责判定诸如犯规、输赢等。 玩家对象接受用户输入,通告棋盘对象,棋盘对象更新棋局画面,同时由裁判对象负责棋局判定。,基于过程的程序设计,面向对

2、象的程序设计,7.2 继承,在面向对象程序设计中,程序由类构成,继承关系是类之间最主要的关系 继承表达“是一种(“is a”)”关系 类Car、Boat、Submarine分别继承Vehicle类,通过继承获得Vehicle类的属性(数据成员)和方法(成员函数) 派生类各自实现Vehicle类界定的派生类必须支持的行为 派生类还可以添加特有的其他属性和方法 继承背后的主要目的是扩展和代码重用,class Vehicle / ; / “:”表示Car继承自Vehicle,称Vehicle为基类,Car为派生类 class Car : public Vehicle / ; class Boat :

3、 public Vehicle / ; class Submarine : public Vehicle / ;,7.2 继承,在C+中,称被继承的类为基类(base class),称继承得到的新类为派生类(derived class),7.2.1 派生类的定义,派生类的定义: class : / 派生类的成员声明 ;,关键字public代表公有继承,如果换成protected,就是保护继承,换成private就是私有继承,C+支持public、protected和private三种类间继承机制,关键字public、private和protected描述基类成员在派生类中的可见性。,7.2.1

4、 派生类的定义,在类继承体系中,基类定义了所有派生类共有的对外公开接口(public interface),派生类继承基类的成员(成员函数和数据成员),派生类还可以改写(override)继承来的成员函数,或者增加新的成员,以实现其独特的行为。,注意:类继承中的关键字public、private和protected描述的是基类成员在派生类中的可见性,而类定义中的public、private和protected是对类成员可见性的约束,不能混淆。,7.2.2 继承的3种方式,1、public继承 public继承保留基类成员函数和数据成员的可见性不变: 基类的public成员,在派生类中还是pub

5、lic的 基类的protected成员,在派生类中还是protected的 基类的private成员对派生类不可见,派生类中不可以调用基类的private成员,在类的public、private和protected三种继承中,派生类都不能访问基类的private成员,从而给了基类一定的私有空间,在基类的private部分改变时,不影响派生类。,class People / 基类 public: walk( ); eat( ); private: / ; class Student : public People / 派生类 public: study(); ;,public继承需要满足派生类“

6、is a”基类,满足面向对象理论中Liskov替换原则:LSP,public 继承,public继承表达的关系是:People类是Student类的基类,Student类是People类的一个派生类,Student类“是一种(“is a”)”People类,如果不能推导出 “is a” 关系,就不应该使用public继承。 在这里,“is a” 是形象的说法,并不严格,public继承要求满足的是面向对象理论中的Liskov替换原则(Liskov Substitution Principle,LSP),意思是“从行为上而言,派生类应该可以完全替换基类完成基类的行为”。,public 继承,下面

7、是一个误用public继承的例子: class Rectangle public: / virtual void setHeight(int newHeight); virtual void setWidth(int newWidth); virtual int height( ) const; / 返回height virtual int width( ) const; / 返回width / ; class Square : public Rectangle / setLength(int newLength); ;,public 继承,Square s; s.setWidth(100);

8、 s.setLength(200); 现在s的长和宽分别是200和100,s不再是正方形,问题出在虽然Square是一种Rectangle,但是Square类不能完全替换Rectangle类完成基类的行为。,public 继承,class Circle : public Ellipse / ; class Penguin : public Bird / ; class Turkey : public Bird / ;,这些问题是同质的,无论具体public继承的是什么,不良的继承设计总是由于派生类无法实现基类一个或多个成员函数给出的接口造成的。解决的办法是要么使基类功能弱一些,派生类功能强一些

9、,要么消除继承关系。绝大多数不良的继承设计都可以归结为“正方形不是矩形”或者“圆不是一种椭圆”的例子。,public 继承,7.2.2 继承的3种方式,2、private继承 基类的public成员成为派生类的private成员 基类的protected成员成为派生类的private成员 基类的private成员对派生类不可见,派生类中不可以调用基类的private成员 基类public或protected成员,由于成了派生类private成员,无法再往下继承,即: 派生类只能调用其直接基类的public或protected成员 在派生类的派生类不可以调用其间接基类的任何成员,class Pe

10、ople / 基类 public: walk( ); eat( ); private: / ; class Et : private People / 派生类 public: study(); ;,private继承是一种实现继承,这里继承的目的是重用People类中walk( )、eat( )方法的实现代码。,private 继承,private 继承,从语义角度上来说,private继承是一种实现继承,private继承和public继承最大的区别就在于,private继承不满足 “is a” 的关系,private继承表达的是“用来实现”。 在实现中使用private继承的目的纯粹为了代

11、码重用,派生类D private继承自基类B,是指D对象用B对象来实现,private继承的目的是利用基类B中的某些代码,而不是基类B和派生类D之间有什么概念上的联系,private继承只是一种实现技术。,private继承不符合Liskov替换原则,派生类不能自动转换成为基类,即使使用类型转换(static_cast或dynamic_cast)也只能得到一个空指针,在private继承下,不可以通过基类指针操作派生类对象: People *p = new ET( ); / 错误,ET不是People,7.2.2 继承的3种方式,3、protected继承 基类的public成员成为派生类的p

12、rotected成员 基类的protected成员也成为派生类的protected成员 基类的private成员对派生类不可见,派生类中不可以调用基类的private成员 与private继承不同,在protected继承下,由于派生类的派生类的成员可以调用基类的protected成员,基类成员可以继续往下继承,protected继承也是实现继承,protected继承和private继承都不表明派生类“是一种(“is a”)”基类。区别是protected继承允许派生类的派生类使用继承关系,如果希望基类成员在派生类的后续派生中延续,就使用 protected继承。,继承访问控制规则,今天编写

13、的代码可以被将来编写的代码调用,class B /基类 public: void foo( ); /基类接口 / ; class D : public B /派生类 / ; class E : public B /派生类 / ; ,7.3 虚函数,今天编写的代码可以调用未来编写的代码,7.3 虚函数,通过继承机制,将一组相关的类组织起来,构成类继承体系; 通过关键字virtual 将基类的成员函数声明为虚函数; 派生类改写(override)从基类继承的虚函数; 支持将派生类对象当作基类对象,传递给基类指针或者初始化基类引用; 支持通过基类指针或引用,动态调用具体派生类改写的虚函数。,C+的做

14、法是:首先定义一个接口,如果类B继承类A,实现类A接口的方法,那么就能在程序运行的时候调用到类B,为实现这个目标,C+提供的支持有:,7.3 虚函数,这样,调用相同的基类接口,面对不同的派生类对象,调用的是不同的实现,即多态:相同的操作,不同的行为。有了多态,就可以实现利用今天编写的代码调用未来编写的派生类的代码。 C+中基类的接口,就是虚函数,在程序运行时,对虚函数的调用,透明地转换为对不同派生类的函数的调用,这在C+中称为动态绑定。,7.3.1 虚函数的定义,例如: class Animal public: / 用关键字virtual 定义虚函数 virtual void eat( ) /

15、* 函数体 */ ;,虚函数是一种非静态的成员函数,定义一个函数为虚函数的方法是在其函数定义前加上关键字virtual,一般形式为: virtual () ,7.3.1 虚函数的定义,class B / 基类B public: virtual void foo( ); / 虚函数 / ; class D : public B / 从B继承 public: virtual void foo( ); / 可以附加virtual关键字,virtual不是必须的 / ; class E : public D / 从D继承 public: void foo( ); / 基类的虚函数在其任意层次的派生类中

16、也还是虚函数 / ; void D:foo( ) / 在类外实现虚函数时,不能再加virtual关键字 / ,7.3.1 虚函数的定义,虚函数只能是类成员函数。 基类声明的虚函数,在派生类及其任意派生层次的派生类中都是虚函数。但为了提高代码的清晰性,可在每一层类的定义中再显式地附加virtual关键字。,注意: 在类外提供虚函数的实现时,不能再加virtual关键字,否则会编译报错,这点和类中const成员函数不一样。 如果在类外实现const成员函数,那么定义和实现处都要有const关键字。 而对于虚函数,在基类定义的地方要加virtual关键字,在派生类的定义处可加可不加virtual关键字,在类外虚函数的

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号