您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 广告经营 > c++类的建立及应用.
Chapter8类——面向对象的核心2面向对象的程序设计本章主要内容§8.1类初步§8.2类的声明与定义§8.3面向对象的设计思想§8.4构造函数和析构函数§8.5this指针§8.6静态成员和常成员§8.7在堆上创建类§8.8友元8.1类初步4面向对象的程序设计一、从结构体到类回顾:通讯录程序structRegist{charname[20];chargender;intage;charaddress[100];};需求:对一条记录进行修改,修改姓名,性别,年龄,地址等数据。5面向对象的程序设计一、从结构体到类按照传统的解决方案,需要编写一个函数VoidChangeValue(Registr,char*n,chars,into,char*ad){strcpy(r.name,n);r.sex=s;r.age=o;strcpy(r.address,ad);}思考:Regist是数据,而ChangeValue是对数据的操作。从逻辑上考虑,它们的关系合理吗?6面向对象的程序设计一、从结构体到类从逻辑上讲,“改变数据”是“记录”的功能,那么“改变”这个动作应该是“记录”这一数据类型的一部分。而在上面的实现中,它们的依存关系是相反的,而这也是典型的“面向过程”思想。设想:能不能把“改变数据”这个动作放到“记录”的内部呢?7面向对象的程序设计一、从结构体到类答案是肯定的,C++语言允许将一个函数放在结构体的内部,并且在这种情况下,函数可以直接访问结构体的成员,于是结构体变成:structRegist{charname[20];charsex;intage;charaddress[100];voidChangeValue(char*n,chars,into,char*ad){……}};8面向对象的程序设计一、从结构体到类可以将这个设置函数直接定义在类的内部。进一步思考:对于一个实用的程序,在ChangeValue函数体内还必须进行更多的判断,例如检查姓名和地址是否超过范围,性别字符是否合法等。而上面的程序中,无法阻止结构体的使用者“绕过”ChangeValue而直接操作成员数据。该如何解决呢?9面向对象的程序设计一、从结构体到类C++语言提供的解决方法:设置访问权限structRegist{private:charname[20];chargender;intage;charaddress[100];public:voidChangeValue(char*n,chars,into,char*ad){……}};private:表示之后的数据外部无法访问public:表示之后的数据外部可以访问在结构体中,默认是public的示例110面向对象的程序设计一、从结构体到类在这些变化之后,struct已经远远超出了C语言中“结构体”的范畴,在C++语言中专门引入了一个新的关键字Class,这就是类。8.2类的声明与定义12面向对象的程序设计一、类的声明structregist{charname[20];charsex;intage;charaddress[100];voidInputRegist();voidSetRegist(char*n,chars,inta,char*d);voidPrintRegist();};类的声明格式:class(struct)类名{private:成员数据;成员函数;public:成员数据;成员函数;protected:成员数据;成员函数;};13面向对象的程序设计类与对象类是一个框架,说明了这种数据类型定义变量的组成方式对象是类的一个实例变量,在内存中占据一定的空间类=声明了一种数据类型,对象=类的变量与结构体变量类似,使用取成员运算符’.’访问对象的成员变量与成员函数二、类和对象的作用域结构体类型结构体变量类类型类的变量类(Class)对象(Object)14面向对象的程序设计二、类和对象的作用域类类型的作用域:在函数定义之外定义的类,其类名的作用域为文件作用域;而在函数体内定义的类,其类名的作用域为块作用域对象的作用域与前面介绍的变量作用域完全相同全局对象局部对象动态对象等15面向对象的程序设计三、成员函数将一个函数的声明放在类的说明,表示该函数属于这个类,是成员函数成员函数的定义可以在类内,但一般是定义在类的外部,定义形式如下:返回值类型类名::函数名(参数列表){......//函数体}16面向对象的程序设计成员函数使用同一个对象的其它成员时,可以直接使用(不用指出对象名)(包括函数成员)在类的成员函数中有三类不同作用域的变量函数的内部变量,类的成员变量,文件的变量逐层隐藏,也可以用域作用符::来指定一个类的所有对象,共享成员函数的代码,成员函数不占据各对象的空间三、成员函数17面向对象的程序设计四、成员的访问权限私有成员(用private说明的)私有成员限定在该类的内部使用私有的数据成员:只允许该类中的成员函数使用,对于私有的成员函数:只能被该类内的成员函数调用;类就相当于私有成员的作用域。18面向对象的程序设计公共成员:关键字public公有成员的数据或函数不受类的限制,可以在类内或类外自由使用;对类而言是透明的保护成员:关键字protected允许在类内及该类的派生类中使用保护的数据或函数(到继承一章再讲)保护成员的作用域是该类及该类的派生类一般我们会将类中的数据成员私有或保护,转而定义一些访问函数来操作他们。四、成员的访问权限19面向对象的程序设计class定义类,不特殊说明,成员是privatestruct定义类,不特殊说明,成员是public私有成员公有成员保护成员类内可以调用可以调用可以调用类外不可调用可以调用不可调用四、成员的访问权限可见,在不考虑继承的情况下,私有和保护成员基本是一样的。20面向对象的程序设计五、例子三角形学生成绩示例2与示例38.3面向对象的设计思想22面向对象的程序设计一、面对对象的概念对象——从程序的角度理解,是对结构体的一种延伸Object—Oriented将数据与对数据进行存在的过程结合在一起的一种程序要素既有数据,又有函数软件开发中一种新的思想和丰富OOAOODOOP23面向对象的程序设计二、OOP的思想将代码和数据放到一个程序要素中,统一进行设计和管理由以函数为中心的设计=》以对象为中心的设计对象是第一位的,函数是属于对象的通过对象来调用函数,而不是过去将数据作为函数的参数有点:逻辑清晰,避免过多分支,减少函数数量24面向对象的程序设计四、OO的特征封装性(Encapsulation)特点数据和方法的结合数据具有隐蔽性(成员的类型),公共、私有、保护成员目的保护对象的数据,避免过分暴露;数据使用更方便;对使用者隐藏实现的细节,使设计、实现和使用分开前提是对类的抽象(abstract)对对象的特征、行为的分析与概括考虑:封装和继承对类的整体思考25面向对象的程序设计继承性(Inheritance)从已有的类中通过增加新的成员的办法,产生的新的类继承的方法:重复使用,增加,修改基类(baseclass)和派生类(derivedclass)单一继承和多重继承形成一个类族26面向对象的程序设计多态性(Polymorphsim)同一个类族中不同的类,具有相同的方法,但是无论在功能还是实现上都上不同的调用哪一个方法是由对象所决定的。8.4构造函数和析构函数28面向对象的程序设计一、对象的建立用已经声明的类来定义一个变量时,就建立的该类的一个对象对象的生命周期和作用域与普通变量相同回忆:结构体变量如何初始化?strutstudentWangqi={10001,”wangqi”,’m’,20,”JinZhou”};思考:类的变量——对象如何初始化?29面向对象的程序设计一、对象的建立鉴于类的复杂性,像结构体那样的直接初始化方式不能满足需求:私有成员无法直接初始化一些成员变量的初始值是通过一个过程计算得到的,无法直接指定值。面向对象的复杂特性决定了不能直接初始化(继承和多态的存在)解决方法之一:定义一个赋值函数,把初始化过程包含在这个函数体中,但是必须显式调用,使用不便。并且这种实现并非真正意义上的“初始化”(上一节中三角形的例子)30面向对象的程序设计二、构造函数C++语言中的解决方法:构造函数(Constructor)类的特殊成员函数名称:与类的名称相同类型:无返值类型调用:自动调用的时机:在建立对象调用,那么:全局对象:在main函数执行前调用;局部对象:对象定义时定义了构造函数之后,在建立对象时,通过给出不同的参数就可以自动调用,完成对象的构建。31面向对象的程序设计二、构造函数classCDate{intyear,month,day;public:CDate(inty,intm,intd);};CDate::CDate(inty,intm,intd){year=y;month=m;day=d;}//两种调用方式CDateday1(2011,5,1);CDateday2=CDate(2011,6,1);构造函数的例子示例432面向对象的程序设计二、构造函数可以通过重载的方式,构造多个参数不同的构造函数,用来以不同的方式初始化对象除了最普通的构造函数,还有几种常见的不同类型的构造函数示例533面向对象的程序设计三、具有缺省参数值的构造函数与普通函数一样,构造函数可以声明参数的缺省值在函数声明中给出缺省值classCDate{CDate(inty=2011,intm=5,intd=1);};CDateday1;CDateday2(2010);CDateday3(2008,6);示例634面向对象的程序设计四、初始化列表也可以不在构造函数中显式的赋值,而是在构造函数定义中的参数列表后加冒号,然后对成员逐个赋值,这一机制叫做初始化列表。列表中初始化的顺序是类定义时成员声明的顺序,而不是列表中的顺序初始化列表的效率很高,并且某些特殊的成员必须在这里得到值,而不能在函数体内赋值。CDate::CDate(inty,intm,intd):year(y),month(m),day(d){}35面向对象的程序设计五、缺省的构造函数没有任何参数的构造函数当定义一个对象切没给出任何参数值是自动调用该构造函数CClock::CClock(){seconds=0;}CClockclock1;一个缺省的构造函数,和一个全部参数值都要缺省值的构造函数不能同时存在如果没有任何构造函数,会自动生成一个缺省构造函数,如果已经定义了任何一个构造函数,就不会自动生成了。示例7;836面向对象的程序设计六、拷贝构造函数构造函数的参数是同类的引用classX{public:X(X&);或X(constX&);};用途:用一个同类对象来初始化为什么要使用引用?用一个对象“初始化出一个相同的对象”,与建立一个新对象再赋值其意义是不同的。如果没有定义拷贝构造函数,编译系统会自动生成一个。进行逐对成员的赋值(byte-wise)示例937面向对象的程序设计六、拷贝构造函数思考:在什么情况下自动生成的拷贝构造函数会失效?示例10PO1OCpyP38面向对象的程序设计七、析构函数(Destructor)思考:下面的程序在构造函数中用malloc分配了一段内存,如果这个类离开作用域之后便消失了,这段分配的内存会怎样呢?classchunk{void*p;public:chunk(intn){p=malloc(n);}};……{chunkc;}//作用域结束了c被自动销毁39面向对象的程序设计七、析构函数(Destructor)结果是:c消失了,但是malloc分配的内存还存在,但却不能使用了,因为指针p已经和对象c一起消失了,造成内存泄漏(memeryleak)。解决方法之一是为chunk类编写一个专门释放内存的函数,但这就要求在chunk的对象被销毁之前调用这个函数,在程序中无疑这是不可能做到的。40
本文标题:c++类的建立及应用.
链接地址:https://www.777doc.com/doc-2901810 .html