资源预览内容
第1页 / 共49页
第2页 / 共49页
第3页 / 共49页
第4页 / 共49页
第5页 / 共49页
第6页 / 共49页
第7页 / 共49页
第8页 / 共49页
第9页 / 共49页
第10页 / 共49页
亲,该文档总共49页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第8章 面向对象技术基础欢迎开启面向对象设计的大门,在第1章中已经简要介绍过面向对象设计的基本理念,本章将具体讲述类和对象的概念。在前面的章节中,程序是由一个个函数组成的,是结构化的编程方法。从本章开始,编写的程序是由对象组成的,将要学习用C+语言进行面向对象的程序设计,当然,面向对象设计也离不开函数等前面讲述的基础知识。8.1 面向对象基本概念“对象”(object)是个抽象的概念,现实世界中的任何事物都可以看成是对象,动物、植物、摩托车、汽车等等都是对象,对象之间有很大的差异,如人和汽车,但有的对象间有相似之处,比如摩托车和自行车,它们有共同的特征(有轮子),同样的功能(人的交通工具),也有不同的特征,如“轮子个数”,“车子重量”等等,基于此,可将“有轮子”,“可更换轮胎”、“能作为人的交通工具”抽象成一个类别(class),可称之为“车”类,摩托车和自行车是该类别的对象。类的提取往往是从两个方面来考虑的,一是特征(C+常称为“属性”)、另一个是功能(C+中常称为“行为”),具备类中定义的“属性”和“行为”的对象都是该类的对象,因此,我们可以说,电动车也是“车”类的对象。8.1.1 类的概念类和对象的关系与 “结构”和“结构体变量”的关系相似。C+用类来描述对象,类是对现实世界中相似事物的抽象,同是“双轮车”的摩托车和自行车,有共同点,也有许多不同点。“车”类是对摩托车、自行车、汽车等相同点和不同点的提取与抽象,如所示。类的定义分为两个部分:数据(相当于属性)和对数据的操作(相当于行为)。从程序设计的观点来说,类就是数据类型,是用户定义的数据类型,对象可以看成某个类的实例(某个类的变量),类和对象的关系与前面介绍的“结构”和“结构体变量”的关系相似,但又有不同,在本章稍后类的定义一节中后具体说明这一问题。8.1.2 类是分层的每一大类中可分成若干小类,也就是说,类是分层的,如图8.2所示。可将所有的图形抽象成“图形”类,该类中共同的属性有很多,这里只取“颜色”这个属性,对所有图形而言,都可定义“显示”操作。同时,“图形”类可进一步分为“一维图形”类、“二维图形”类和其他类,根据形状的不同,“一维图形”类可进一步分为“直线”类和“折线”类,“二维图形”类又可分为“正方形”类和“圆”类。下层的类除了“继承”了上层类中定义的属性和行为外,还可增加新的属性和行为(如“圆”类相比“二维图形”类增加了“圆心”和“半径”属性,增加了“求面积”这一行为),甚至可以在下层类中重新定义上层类已定义的属性和行为(如“直线”类、“折线类”、“正方形”类和“圆”类中都重新定义了“图形”类中已定义的“显示”操作)。8.1.3 类和对象的关系对象需要从属性和行为两个方面进行描述,类是对象的封装。类的使用主要有以下几个步骤:定义一个类,C+中,分别用数据成员和函数成员来表现对象的属性和行为。类的定义强调“信息隐藏”,将实现细节和不允许外部随意访问的部分屏蔽起来。因此,在类定义中,需要用public或private将类成员区分开(此外,还有protected型的数据成员,稍后会有详细介绍),外界不能访问程序的private成员,只能访问public数据成员,对象间的信息传送也只能通过public成员函数,保证了对象的数据安全。类的实现,即进一步定义类的成员函数,使各个成员函数相互配合以实现接口对外提供的功能,类的定义和实现是由类设计者完成的。通过该类声明一个属于该类的变量(即对象),并调用其接口(即public型的数据成员或函数成员),这是使用者的工作。8.2 C+类的定义先来看一下类是如何定义的,对一些通用的问题,前人已经定义好了很多的类,比如微软的MFC类库,程序员不必关心其内部细节,只要抱着“拿来主义”的态度就好,但对某些特殊问题来说,必须由自己提炼模型,进行类的定义。8.2.1 类定义的基本形式C+中使用关键字class定义一个类,其基本形式如下:class类名public:公共成员函数private:私有成员函数私有的数据成员定义;8.2.2 类定义示例对一台计算机来说,它有如下特征:属性:品牌、价格。方法:输出计算机的属性。实现了computer类的定义:8.2.3 class和structclass的定义看上去很像struct定义的扩展,事实上,类定义时的关键字class完全可以替换成struct,也就是说,第5章中介绍的结构体变量也可以有成员函数。class和struct的唯一区别在于:struct的默认访问方式是public,而class为private。提示:通常使用class来定义类,而把struct用于只表示数据对象、没有成员函数的类。8.3 C+类的实现类的实现就是定义其成员函数的过程,类的实现有两种方式:一是在类定义时同时完成成员函数的定义。另一是在类定义的外部定义其成员函数。8.3.1 在类定义时定义成员函数成员函数的实现可以在类定义时同时完成,如:(详细内容请参照本书)8.3.2 在类定义的外部定义成员函数在类定义的外部定义成员函数时,应使用作用域操作符(:)来标识函数所属的类,即有如下形式:返回类型 类名:成员函数名(参数列表)函数体其中,返回类型、成员函数名和参数列表必须于类定义时的函数原型一致,这样,可改写为:8.4 C+类的使用定义了一个类之后,便可以如同用int、double等类型符声明简单变量一样,创建该类的对象,称为类的实例化。由此看来,类的定义实际上是定义了一种类型,类不接收或存储具体的值,只作为生成具体对象的“蓝图”,只有将类实例化,创建对象(声明类的变量)后,系统才为对象分配存储空间。8.4.1 声明一个对象使用类定义声明了一个对象,并利用对象名实现了public成员函数的调用:8.4.2 对象的作用域、可见域和生存期对象的作用域、可见域和生存期与普通变量,如int型变量的作用域、可见域和生存期并无不同,对象同样有局部、全局和类内(稍后就将对对象成员进行介绍)之分,对于在代码块中声明的局部对象,在代码块执行结束退出时,对象会被自动撤销,对应的内存会自动释放(当然,如果对象的成员函数中使用了new或malloc申请了动态内存,却没有使用delete或free命令释放,对象撤销时,这部分动态内存不会自动释放,造成内存泄露)。8.5. 对象的创建和撤销中,通过自定义的公共成员函数SetBrand是SetPrice实现对对象数据成员的初始化,实际上,C+为类提供了两种特殊的成员函数,一是构造函数,在对象创建时自动调用,用以完成对象成员变量等的初始化及其他操作(如为指针成员动态申请内存空间等);另一个是析构函数,在对象撤销时自动调用,用以执行一些清理任务,如释放成员函数中动态申请的内存等。8.5.1 构造函数的作用当对象被创建时,构造函数自动被调用。构造函数有一些独特的地方:函数的名字与类名相同,没有返回类型和返回值。其主要工作有:给对象一个标识符。为对象数据成员开辟内存空间。完成对象数据成员的初始化(函数体内的工作,由程序员完成)。上述3点也说明了构造函数的执行顺序,在执行函数体之前,构造函数已经为对象的数据成员开辟了内存空间,这时,在函数体内对数据成员的初始化便是顺理成章了。8.5.2 构造函数可以有参数编译器自动生成的缺省构造函数是无参的,实际上,构造函数可以接收参数,在对象创建时提供更大的自由度,如代码8-5:8.5.3 构造函数支持重载前面说,一旦程序员为一个类定义了构造函数,编译器便不会为类自动生成缺省构造函数,因此,如果还想使用无参的构造函数,如“point pt1;”的形式必须在类定义中显式定义一个无参构造函数。这样,构造函数就会出现两个,会不会有问题呢?不会,构造函数支持重载,在创建对象时,根据传递的具体参数决定采用哪个构造函数。8.5.4 构造函数允许按参数缺省方式调用中的构造函数可以作如下定义:point(int x0,int y0)cout对象创建时构造函数被自动调用endl;xPos=x;yPos=y;此时,允许在创建对象时缺省参数,下列声明语句都是合法的:point pt;point pt(3);point pt(3,4);8.5.5 初始化表达式除了在构造函数体内初始化数据成员外,还可以通过成员初始化表达式来完成。成员初始化表可用于初始化类的任意数据成员(后面要介绍的static数据成员除外),该表达式由逗号分隔的数据成员表组成,初值放在一对圆括号中。只要将成员初始化表达式放在构造函数的头和体之间,并用冒号将其与构造函数的头分隔开,便可实现数据成员表中元素的初始化,对而言,下述代码:point(int x,int y)cout有参构造函数的调用endl;xPos=x;yPos=y;等价于:point(int x,int y):xPos(x),yPos(y)cout有参构造函数的调用数据成员”的方式来存取类数据成员。举例来说:class Exprivate:int x;int y;public:void Set()x=1;y=2;8.9.5 对象数组对象数组和标准类型数组的使用方法并没有什么不同,也有声明、初始化和使用3个步骤。8.9.6 对象链表对象链表中,节点的初始化需要构造函数来完成,除此之外,对象链表和第5章中介绍的链表并无不同。8.10 为对象动态分配内存和把一个简单变量创建在动态存储区一样,可以用new和delete为对象分配动态存储区,在复制构造函数一节中已经介绍了为类内的指针成员分配动态内存的相关范例,本节主要讨论如何为对象和对象数组动态分配内存。8.10.1 使用new和delete为单个对象分配/释放动态内存演示了如何为单个对象动态内存分配。8.10.2 使用new和delete为对象数组分配/释放动态空间使用new为对象数组分配动态空间时,不能显式调用对象的构造函数,因此,对象要么没有定义任何形式的构造函数(由编译器缺省提供),要么显式定义了一个(且只能由一个)所有参数都有缺省值的构造函数。8.10.3 malloc和free能否为对象动态申请内存malloc/free无法满足动态对象的要求,因为malloc和free无法像new/delete及new/delete那样自动调用对象的构造函数和析构函数。8.11 小结本章讲述了C+语言中面向对象编程的基本概念和方法。C+通过class关键字可以定义类,类的成员包括数据成员和函数成员两种。关于类的使用,大体分为类的定义、类的实现和类对象的创建3个步骤,其中,类的定义指明了类的结构,相当于“蓝图”,而类的实现相当于“技术图纸”,根据定义和实现便可以声明一个类的对象。类中有几个特殊的成员函数,构造函数、复制构造函数和析构函数。构造函数和复制构造函数用于为类对象开辟所需内存空间,而析构函数则是在撤销对象时,释放其内存空间,但需要注意的是,用户通过new申请的动态内存并不会在对象撤销时被自动释放,所以,应合理搭配new和delete,及时释放无用的动态内存。构造函数不能由用户调用,但析构函数可以显式调用。复制构造函数的形参是本类对象的引用,它是用一个对 象来初始化另一个对象。如果编程者没有显式定义构造函数(包括复制构造函数),C+编译器就隐式定义缺省的构造函数。
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号