c++程序设计第7章-类与对象课件_第1页
c++程序设计第7章-类与对象课件_第2页
c++程序设计第7章-类与对象课件_第3页
c++程序设计第7章-类与对象课件_第4页
c++程序设计第7章-类与对象课件_第5页
已阅读5页,还剩91页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第7章类与对象(一)面向对象的基本概念类的定义创建对象构造函数与析构函数对象数组this指针静态成员友元类的作用域12/19/20221类和对象第7章类与对象(一)面向对象的基本概念12/16/2022面向对象的基本概念*1.面向对象与面向过程的区别:我要开车去新疆面向过程我开车,我过陕西,我过兰州……面向对象我命令车去新疆车怎么去我不关心(封装)12/19/20222类和对象面向对象的基本概念*1.面向对象与面向过程的区别:12/12.类(class)和对象(object)的概念对象是系统中用来描述客观事务的一个实体,它通过“属性attribute(数据成员)”和“行为behavior(成员函数、方法)”来分别实体的静态属性和动态属性。类是具有共同属性和行为的对象的抽象。对象是类的实例(instance)。学生A抽象类对象学生学号姓名学习()学生A学号=101姓名=TOM实例化12/19/20223类和对象2.类(class)和对象(object)的概念对象是系统中*3.类(对象)之间的关系关联关系教师姓名教学(学生A)学生学号姓名学习()学校12/19/20224类和对象*3.类(对象)之间的关系关联关系教师姓名教学(学生A)继承关系(一般和特殊)xx是一种XX类的继承层次12/19/20225类和对象继承关系(一般和特殊)xx是一种XX类的继承层次12/16/聚合关系(整体和部分)队长队员球队聚集头身体人组合12/19/20226类和对象聚合关系(整体和部分)队长队员球队聚集头身体人组合1多态车go()大卡车go()小汽车go()12/19/20227类和对象多态车go()大卡车go()小汽车go()12/16/202面向对象的设计思想有那些类(对象)?每一种类(对象)有哪些属性和方法?类(对象)之间有哪些关系?12/19/20228类和对象面向对象的设计思想有那些类(对象)?12/16/20228类类的定义类的定义格式一般分为说明部分和实现部分。说明部分:是用来说明类中的成员,包含数据成员的说明和成员函数的说明。成员函数是用来对数据成员进行操作的,也称为“方法”。实现部分:是用来对成员函数进行定义。12/19/20229类和对象类的定义类的定义格式一般分为说明部分和实现部分。12/16/说明部分的一般格式class类类型名{

public:公有成员说明

private:

私有成员说明};私有访问权限,为默认值,可缺省公有访问权限除本类中的成员函数及友元外,其他类外函数不能访问。程序中的任何函数都可访问12/19/202210类和对象说明部分的一般格式class类类型名私有访问权限,为默认值例如:定义一个Person类,设Person具有的特征:属性(姓名、年龄、性别),方法(输出一个人的属性);则对应着有4个成员:三个数据成员,一个成员函数。三个数据成员定义为私有成员,print成员函数定义为公有成员。则有:classCPerson{

public:voidprint();

private:charname[10];intage;charsex;};类名通常用C字母开始,以区别其他标识符12/19/202211类和对象例如:定义一个Person类,设Person具有的特征:属性类的实现部分类的实现部分即定义它的成员函数,如在类说明内部定义,则方式与定义普通函数大体相同。若在类说明外部定义成员函数,则应使用类域运算符::(p21)指明该函数是哪个类中的成员函数。格式为:函数类型类名::成员函数名(形参表){函数体;}voidCPerson::print(){cout<<name<<age<<sex<<endl;}除特殊指明外,成员函数操作的是同一对象中的数据成员。不同的类允许有相同名称的成员函数,因此,在类外定义成员函数的实现时,必须在成员函数名前加上所属类名和作用域操作符“::”。12/19/202212类和对象类的实现部分类的实现部分即定义它的成员函数,如在类说明内部定当成员函数的规模较小时,可在类中定义成员函数,成为内联成员函数。例:classCDate{

public:voidsetDate(intm,intd,inty)//置日期值{ month=m;day=d;year=y;} voidprint();

private:intmonth,day,year;};voidCDate::print(){cout<<year<<'.'<<month<<'.'<<day<<endl;}若将内联成员函数定义在类说明之外则要加上inline。内联成员函数12/19/202213类和对象当成员函数的规模较小时,可在类中定义成员函数,成为内联成员函注意事项1.在类体中不允许对所定义的数据成员进行初始化。classCDate{public:…private:intyear(1998),month(4);…};2.类中的数据成员的类型可以是任意的,包括整型、浮点型、字符型、数组、指针和引用等,也可以是另一个类的对象。3.习惯将类的定义代码放到一个头文件中,以后若要使用则用文件包含命令包含。错误testClass\CreateClass.cpp12/19/202214类和对象注意事项1.在类体中不允许对所定义的数据成员进行初始化。错误创建对象1.对象的定义形式为:类名

对象名列表;

CDatedate1,date2;//定义两个CDate类的对象date1和date2

CDate*pDate=&date1;

//定义一个指向date1对象空间的指针pDateCDate&rDate=date2;//定义一个引用对象rDateCDatedata[3];//定义一个data对象数组,其元素类型为CDate类定义了一个类只是定义了一种类型,它并不分配空间,不能进行操作。只有用它创建对象后,系统才为对象分配存储空间。12/19/202215类和对象创建对象1.对象的定义形式为:定义了一个类只是定义了一种类型成员的访问通过对象可以访问类中的公有类型数据和成员函数。其使用方式为:

对象名.成员函数名对象名.数据成员例:date1.year=2002;date1.Print();用指针访问对象公有成员:指针名->数据成员或指针名->成员函数(*指针名).数据成员或(*指针名).成员函数例:pDate->day=30;pDate->Print();(*pDate).day=30;(*pDate).Print();用引用访问对象成员:引用名.数据成员或引用名.成员函数例:rDate.year=2008;rDate.Print();12/19/202216类和对象成员的访问通过对象可以访问类中的公有类型数据和成员函数。其使注意:在成员函数中访问成员无须加对象名来作为前缀。如:voidCDate::print(){cout<<year<<'.'<<month<<'.'<<day<<endl;}在year等成员之前不能加对象名,在定义类时,成员函数是所有对象共享的代码,不被某一个对象独占。也无法确定类的对象名。注意12/19/202217类和对象注意:注意12/16/202217类和对象例一个完整的程序//CDate.hclassCDate{public:voidsetDate(intm,intd,inty)//置日期值{ month=m;day=d;year=y;} voidprint();private:intmonth,day,year;};voidCDate::print(){cout<<year<<'.'<<month<<'.'<<day<<endl;}12/19/202218类和对象例一个完整的程序//CDate.h12/16/202218续例一个完整的程序#include<iostream.h>#include"CDate.h"voidmain(){CDatedate1;date1.setDate(8,5,1996);date1.print();

//cout<<date1.year<<endl;/*CDate*pDate=&date1;pDate->print();*/}testClass\testCDate.cpp12/19/202219类和对象续例一个完整的程序#include<iostream.类的成员函数内联函数:指定义在类体内的成员函数。外联函数:指说明在类体内,定义在类体外的成员函数。类外定义的函数缺省情况下都是外联函数,用关键字inline

可以强制转换。

对于内联成员函数,编译时在所有调用该函数的地方将装入实际的函数代码。1.内联函数和外联函数12/19/202220类和对象类的成员函数内联函数:指定义在类体内的成员函数。对于内联成classCDate{public:voidsetDate(intm,intd,inty)//内联函数之一{ month=m;day=d;year=y;}voidprint();private:intmonth,day,year;};inlinevoidCDate::print()//内联函数之二{cout<<year<<'.'<<month<<'.'<<day<<endl;}12/19/202221类和对象classCDate12/16/202221类和对象2.设置参数的缺省值函数在定义时可以预先定义出形参的缺省值。调用时如果给出实参,则用实参初始化形参,如果没有给出实参,则采用预先定义形参的缺省值。例如:voidsetDate(intm,intd=28,inty=2008);

//缺省参数按从右往左的方式或voidsetDate(intm,intd=28,inty=2008){…}在进行函数调用时,主调函数的实参与被调函数的形参按从左到右的位置结合。TestParaDefault.cpp12/19/202222类和对象2.设置参数的缺省值函数在定义时可以预先定义出形参的缺省值3.函数的重载函数的重载:出现在相同作用域的两个函数,如果具有相同的名字而形参表不同,则称为重载函数(overloadedfunction)。调用时,会根据不同的参数表选择对应的成员函数。重载函数,必须:函数名相同,函数的作用域相同,函数的参数个数或参数类型不同。使用重载函数时应注意:⑴只有返回值不同,不能成为重载函数。

intmax(inta,intb);doublemax(inta,intb); //错误⑵使用带缺省值的函数时,可能引发错误。如:

intmax(inta,intb=0);intmax(intc);当用一个实参调用该函数时,如max(2),则会出现调用歧义性12/19/202223类和对象3.函数的重载函数的重载:出现在相同作用域的两个函数,如果构造函数和析构函数构造函数和析构函数都是类的成员函数,是特殊的成员函数,不能被调用而由系统自动调用/执行。构造函数名与类名相同;析构函数名为类名前加“~”。构造函数的功能是在创建对象时给对象分配内存空间,并可使用给定值来初始化对象。析构函数的功能是用来释放一个对象的已分配空间。并可在对象被清除前,完成一些清理工作。12/19/202224类和对象构造函数和析构函数构造函数和析构函数都是类的成员函数,是特殊对前面的日期类进行修改,并将定义存放在CDate1.h文件中。如:classCDate1

{public:CDate1(inty,intm,intd);~CDate1();voidprint();private:intyear,month,day;

};函数名与类名一致,无类型但可有参数名字与类名一致,前有~,无类型无参数12/19/202225类和对象对前面的日期类进行修改,并将定义存放在CDate1.h文件中CDate1::CDate1(intm,intd,inty){month=m;day=d;year=y;cout<<"Constructorcalled.\n";}CDate1::~CDate1(){cout<<"Destructorcalled.\n";}voidCDate1::print(){cout<<year<<"."<<month<<"."<<day<<endl;}与其他成员函数定义一样,两种函数的定义可放在类体内,也可放在类体外12/19/202226类和对象CDate1::CDate1(intm,intd,int#include<iostream.h>#include"CDate1.h"voidmain(){CDate1today(2007,4,1),tomorrow(2007,4,2);cout<<"todayis";today.print();cout<<"tomorrowis";tomorrow.print();}执行程序后,输出结果为:函数结束时,自动调用析构ConstructorCalled.ConstructorCalled.todayis2007.4.1tomorrowis2007.4.2Destructorcalled.Destructorcalled.12/19/202227类和对象#include<iostream.h>函数结束时,自动调构造函数的特点有:程序中一般不直接调用构造函数,在创建对象时系统自动调用构造函数。构造函数可以重载,即可定义多个参数个数不同的函数构造函数有隐含的返回值,并由系统内部使用析构函数的特点有:一个类中只能定义一个析构函数,即不能重载析构函数可以被调用,也可系统调用被自动调用的情况有两种:在一个函数体内定义的一个对象,当函数结束时用new运算符动态创建的一个对象,在使用delete释放时12/19/202228类和对象构造函数的特点有:12/16/202228类和对象缺省构造函数和缺省析构函数在类定义中可以不定义任何构造函数,这时编译器会自动生成一个不带参数的缺省构造函数。其格式为:

<类名>::<缺省构造函数名>(){}则在程序中定义一个对象而未指明初始化时,编译器便按缺省构造函数来初始化该对象。若定义了构造函数,则编译器就不会再生成缺省构造函数,必须使用定义的构造函数创建对象。同理,若一个类中未定义析构函数,编译系统也生成一个缺省析构函数。其格式为:<类名>::~<缺省析构函数名>(){}这也是前面的程序中可以没有构造和析构函数的原因12/19/202229类和对象缺省构造函数和缺省析构函数在类定义中可以不定义任何构造函数,classCConstruct{ public:CConstruct(intx,inty);CConstruct(); voidprint(); private: intm1,m2;};CConstruct::CConstruct(intx,inty){ m1=x; m2=y;}CConstruct::CConstruct(){ m1=0; m2=0;}TestConsOverLoad.cpp例:12/19/202230类和对象classCConstructTestConsOverLovoidCConstruct::print(){cout<<m1<<","<<m2<<endl;}voidmain(){ CConstructc2; CConstructc1(3,4);c1.print();}不带参数创建对象,调用无参构造函数12/19/202231类和对象voidCConstruct::print()不带参数创拷贝初始化构造函数构造函数除可以用基本数据类型初始化对象外,还可以使用已存在的同类型的对象即类类型的对象来初始化正在创建的对象。为此,必须在类中定义一个特殊的构造函数来完成这个工作,这个构造函数被称为拷贝初始化构造函数。格式为:<类名>::<拷贝初始化构造函数名>(<类名>&<引用名>){…}如:student::student(student&s){…}每个类中必须有一个。若类中未说明,则编译系统会自动生成缺省函数。12/19/202232类和对象拷贝初始化构造函数构造函数除可以用基本数据类型初始化对象外,classCMyClass{ public: CMyClass(intx); CMyClass(CMyClass&c); private: intmember;};CMyClass::CMyClass(intx){member=x;}CMyClass::CMyClass(CMyClass&c){ cout<<"copyconstructorcalled"<<endl; member=c.member;}拷贝初始化构造函数TestCopyConstructor.cpp12/19/202233类和对象classCMyClass拷贝初始化构造函数TestCo拷贝初始化构造函数被自动调用有三种情况:一、是用一个已知对象初始化一个新对象时。二、是以值调用方式向一个函数传递对象参数时。三、当对象作为函数返回值时。CMyClassfun(CMyClassd);voidmain(){ CMyClassb(3);

CMyClassc(b); CMyClasss=fun(c);}CMyClassfun(CMyClassd){ returnd;}12/19/202234类和对象拷贝初始化构造函数被自动调用有三种情况:12/16/2022内存解析member:3bMyClass(intx)MyClass(MyClass&c)cmember:3member:3dmember:3*member:3s12/19/202235类和对象内存解析member:3bMyClass(intx)MyC对象数组对象数组:一个数组中的每个数组元素都为同一类的对象。对象数组的定义有以下几种形式:类中只有无参的构造函数类名数组名[常量表达式];例:CDate2objArray[4];类中只有需要参数的构造函数类名数组名[常量表达式]={构造函数名(参数表),…,构造函数名(参数表)};例:CDate2objArray[2]={CDate1(2002,3,4),CDate1(2008,5,26)};类中有无参的构造函数和有参的构造函数12/19/202236类和对象对象数组对象数组:一个数组中的每个数组元素都为同一类的对访问数组元素对象的成员objArray[1].print()或(objArray+1)->print()testObjectArray.cpp12/19/202237类和对象访问数组元素对象的成员testObjectArray.cpp每一个类的非静态成员函数中的都有一个指针形参this,用于指向正在操作该成员函数的对象。例如:classCDate3{ public: CDate3(inty,intm,intd); voidprint(CDate3*t); voidprint(); private: intyear,month,day;};CDate3::CDate3(inty,intm,intd){ year=y;month=m; day=d;}this指针testThis.cpp12/19/202238类和对象每一个类的非静态成员函数中的都有一个指针形参this,用于voidCDate3::print(CDate3*t){cout<<t->year<<"."<<t->month<<"."<<t->day<<endl;}voidCDate3::print(){cout<<this->year<<"."<<this->month<<"."<<this->day<<endl;}#include<iostream.h>#include"CDate3.h"voidmain(){ CDate3objThis(2008,4,23);objThis.print(&objThis);objThis.print();}隐含的指针形参this12/19/202239类和对象voidCDate3::print(CDate3*t)隐静态成员定义类时,可用关键字static声明的数据成员或成员函数称为静态成员,包括静态数据成员和静态成员函数。静态数据成员是在编译时被创建,与对象是否存在无关,其内存空间为数据区,其生命期一直到程序结束。静态数据成员必须在类外初始化:

数据类型类名::成员名=初始值;静态成员函数属于类,而不是对象成员(无this指针用来存放对象的地址),不能直接引用具体对象中的非静态成员。须使用(对象名.成员名)来引用。可以通过对象名或类名来访问静态成员。12/19/202240类和对象静态成员定义类时,可用关键字static声明的数据成员或成员静态数据成员#include<iostream.h>classCCat{ public:

staticintcount; CCat(intcolor) {count++;colorFur=color;} private: intcolorFur;};intCCat::count=0;voidmain(){CCatmm(0);CCatpp(1);cout<<CCat::count<<endl;cout<<mm.count<<endl;}CCat::count++12/19/202241类和对象静态数据成员#include<iostream.h>CCa静态成员函数classM{public:M(inta){A=a;}

staticvoidf1(Mm);private:intA;staticintB;};intM::B=0;voidM::f1(Mm){cout<<m.A<<B<<endl;}voidmain(){Mp(5);

M::f1(p);//p.f1(p);}静态成员声明静态成员定义引用非静态成员引用静态成员函数testStaticFunction.cpp12/19/202242类和对象静态成员函数classM{静态成员声明静态成员定义引用非静友元函数在某个类定义中用friend说明一个外部函数后,这个外部函数就可直接访问该类的任何私有成员。则该外部函数称为这个类的友元函数。采用友元的目的主要是为提高效率。显然它破坏了类的封装性。注意:在某个类中说明的友元函数并不是该类的成员函数。它可以是外部的一个独立函数,也可以是另外一个类中的成员函数。12/19/202243类和对象友元函数在某个类定义中用friend说明一个外部函数后,这个classCFriend{

friendvoidgFunc1(CFriend&p);

//声明友元函数private: voidfunc1(){cout<<"friend\n";}};友元为外部的独立函数voidgFunc1(CFriend&p)//定义外部友元函数,使用类对象引用作参数//注:不是成员函数不加类名::{ p.func1();//友元的使用,调用私有成员 …}testFriendFunction.cpp12/19/202244类和对象classCFriend友元为外部的独立函数voidgclassCFriendB;classCFriendA{public:intf1(CFriendB&b);//类中使用另一个类对象须先有其说明intf2(CFriendB&b);};classCFriendB{friendintCFriendA::f1(CFriendB&b);//把CFriendA中f1说明为友元private:staticintm;};intCFriendB::m=5;intCFriendA::f1(CFriendB&b){returnb.m;}//正确:

intCFriendA::f2(CFriendB&b){returnb.m;}//错误:友元为另一个类的成员函数testFriendFunction2.cpp12/19/202245类和对象classCFriendB;友元为另一个类的成员函数tes同函数一样,类也可以声明为另一个类的友元,称为友元类。若A为B的友元类,则A类的所有成员函数都是B类的友元函数,都可以访问B类的私有和保护成员。声明的形式为:classB{

friendclassA; …};注意:1)友元关系是不能传递的。2)友元关系是是单向的。友元类testFriendClass.cpp12/19/202246类和对象同函数一样,类也可以声明为另一个类的友元,称为友元类。cla类的作用域类的作用域(简称类域)是指类的定义中由一对花括号括起的部分。类的所有成员都在类的作用域中。类域区分符“::”来确定成员函数的类域,从而可在类外定义成员函数。同变量一样,在类定义体和函数体外定义的对象为全局对象,而在类定义体内或在函数体内定义的对象为局部对象。全局对象的作用域是从定义它的位置开始直至文件的结束,而局部对象的作用域只在类作用域或函数体内。12/19/202247类和对象类的作用域类的作用域(简称类域)是指类的定义中由一对花括号括#include<iostream.h>intpp=0;classCScope{public:

intpp;voidrp(intpp);};voidCScope::rp(intpp){

::pp=11; //变量名前加域区分符给全局变量pp赋值this->pp=100;

//给数据成员赋值cout<<pp<<endl;}voidmain(){CScopea;a.rp(4);cout<<pp<<'\n'<<a.pp<<endl;}testScope.cpp12/19/202248类和对象#include<iostream.h>testSco第7章类与对象(一)面向对象的基本概念类的定义创建对象构造函数与析构函数对象数组this指针静态成员友元类的作用域12/19/202249类和对象第7章类与对象(一)面向对象的基本概念12/16/2022面向对象的基本概念*1.面向对象与面向过程的区别:我要开车去新疆面向过程我开车,我过陕西,我过兰州……面向对象我命令车去新疆车怎么去我不关心(封装)12/19/202250类和对象面向对象的基本概念*1.面向对象与面向过程的区别:12/12.类(class)和对象(object)的概念对象是系统中用来描述客观事务的一个实体,它通过“属性attribute(数据成员)”和“行为behavior(成员函数、方法)”来分别实体的静态属性和动态属性。类是具有共同属性和行为的对象的抽象。对象是类的实例(instance)。学生A抽象类对象学生学号姓名学习()学生A学号=101姓名=TOM实例化12/19/202251类和对象2.类(class)和对象(object)的概念对象是系统中*3.类(对象)之间的关系关联关系教师姓名教学(学生A)学生学号姓名学习()学校12/19/202252类和对象*3.类(对象)之间的关系关联关系教师姓名教学(学生A)继承关系(一般和特殊)xx是一种XX类的继承层次12/19/202253类和对象继承关系(一般和特殊)xx是一种XX类的继承层次12/16/聚合关系(整体和部分)队长队员球队聚集头身体人组合12/19/202254类和对象聚合关系(整体和部分)队长队员球队聚集头身体人组合1多态车go()大卡车go()小汽车go()12/19/202255类和对象多态车go()大卡车go()小汽车go()12/16/202面向对象的设计思想有那些类(对象)?每一种类(对象)有哪些属性和方法?类(对象)之间有哪些关系?12/19/202256类和对象面向对象的设计思想有那些类(对象)?12/16/20228类类的定义类的定义格式一般分为说明部分和实现部分。说明部分:是用来说明类中的成员,包含数据成员的说明和成员函数的说明。成员函数是用来对数据成员进行操作的,也称为“方法”。实现部分:是用来对成员函数进行定义。12/19/202257类和对象类的定义类的定义格式一般分为说明部分和实现部分。12/16/说明部分的一般格式class类类型名{

public:公有成员说明

private:

私有成员说明};私有访问权限,为默认值,可缺省公有访问权限除本类中的成员函数及友元外,其他类外函数不能访问。程序中的任何函数都可访问12/19/202258类和对象说明部分的一般格式class类类型名私有访问权限,为默认值例如:定义一个Person类,设Person具有的特征:属性(姓名、年龄、性别),方法(输出一个人的属性);则对应着有4个成员:三个数据成员,一个成员函数。三个数据成员定义为私有成员,print成员函数定义为公有成员。则有:classCPerson{

public:voidprint();

private:charname[10];intage;charsex;};类名通常用C字母开始,以区别其他标识符12/19/202259类和对象例如:定义一个Person类,设Person具有的特征:属性类的实现部分类的实现部分即定义它的成员函数,如在类说明内部定义,则方式与定义普通函数大体相同。若在类说明外部定义成员函数,则应使用类域运算符::(p21)指明该函数是哪个类中的成员函数。格式为:函数类型类名::成员函数名(形参表){函数体;}voidCPerson::print(){cout<<name<<age<<sex<<endl;}除特殊指明外,成员函数操作的是同一对象中的数据成员。不同的类允许有相同名称的成员函数,因此,在类外定义成员函数的实现时,必须在成员函数名前加上所属类名和作用域操作符“::”。12/19/202260类和对象类的实现部分类的实现部分即定义它的成员函数,如在类说明内部定当成员函数的规模较小时,可在类中定义成员函数,成为内联成员函数。例:classCDate{

public:voidsetDate(intm,intd,inty)//置日期值{ month=m;day=d;year=y;} voidprint();

private:intmonth,day,year;};voidCDate::print(){cout<<year<<'.'<<month<<'.'<<day<<endl;}若将内联成员函数定义在类说明之外则要加上inline。内联成员函数12/19/202261类和对象当成员函数的规模较小时,可在类中定义成员函数,成为内联成员函注意事项1.在类体中不允许对所定义的数据成员进行初始化。classCDate{public:…private:intyear(1998),month(4);…};2.类中的数据成员的类型可以是任意的,包括整型、浮点型、字符型、数组、指针和引用等,也可以是另一个类的对象。3.习惯将类的定义代码放到一个头文件中,以后若要使用则用文件包含命令包含。错误testClass\CreateClass.cpp12/19/202262类和对象注意事项1.在类体中不允许对所定义的数据成员进行初始化。错误创建对象1.对象的定义形式为:类名

对象名列表;

CDatedate1,date2;//定义两个CDate类的对象date1和date2

CDate*pDate=&date1;

//定义一个指向date1对象空间的指针pDateCDate&rDate=date2;//定义一个引用对象rDateCDatedata[3];//定义一个data对象数组,其元素类型为CDate类定义了一个类只是定义了一种类型,它并不分配空间,不能进行操作。只有用它创建对象后,系统才为对象分配存储空间。12/19/202263类和对象创建对象1.对象的定义形式为:定义了一个类只是定义了一种类型成员的访问通过对象可以访问类中的公有类型数据和成员函数。其使用方式为:

对象名.成员函数名对象名.数据成员例:date1.year=2002;date1.Print();用指针访问对象公有成员:指针名->数据成员或指针名->成员函数(*指针名).数据成员或(*指针名).成员函数例:pDate->day=30;pDate->Print();(*pDate).day=30;(*pDate).Print();用引用访问对象成员:引用名.数据成员或引用名.成员函数例:rDate.year=2008;rDate.Print();12/19/202264类和对象成员的访问通过对象可以访问类中的公有类型数据和成员函数。其使注意:在成员函数中访问成员无须加对象名来作为前缀。如:voidCDate::print(){cout<<year<<'.'<<month<<'.'<<day<<endl;}在year等成员之前不能加对象名,在定义类时,成员函数是所有对象共享的代码,不被某一个对象独占。也无法确定类的对象名。注意12/19/202265类和对象注意:注意12/16/202217类和对象例一个完整的程序//CDate.hclassCDate{public:voidsetDate(intm,intd,inty)//置日期值{ month=m;day=d;year=y;} voidprint();private:intmonth,day,year;};voidCDate::print(){cout<<year<<'.'<<month<<'.'<<day<<endl;}12/19/202266类和对象例一个完整的程序//CDate.h12/16/202218续例一个完整的程序#include<iostream.h>#include"CDate.h"voidmain(){CDatedate1;date1.setDate(8,5,1996);date1.print();

//cout<<date1.year<<endl;/*CDate*pDate=&date1;pDate->print();*/}testClass\testCDate.cpp12/19/202267类和对象续例一个完整的程序#include<iostream.类的成员函数内联函数:指定义在类体内的成员函数。外联函数:指说明在类体内,定义在类体外的成员函数。类外定义的函数缺省情况下都是外联函数,用关键字inline

可以强制转换。

对于内联成员函数,编译时在所有调用该函数的地方将装入实际的函数代码。1.内联函数和外联函数12/19/202268类和对象类的成员函数内联函数:指定义在类体内的成员函数。对于内联成classCDate{public:voidsetDate(intm,intd,inty)//内联函数之一{ month=m;day=d;year=y;}voidprint();private:intmonth,day,year;};inlinevoidCDate::print()//内联函数之二{cout<<year<<'.'<<month<<'.'<<day<<endl;}12/19/202269类和对象classCDate12/16/202221类和对象2.设置参数的缺省值函数在定义时可以预先定义出形参的缺省值。调用时如果给出实参,则用实参初始化形参,如果没有给出实参,则采用预先定义形参的缺省值。例如:voidsetDate(intm,intd=28,inty=2008);

//缺省参数按从右往左的方式或voidsetDate(intm,intd=28,inty=2008){…}在进行函数调用时,主调函数的实参与被调函数的形参按从左到右的位置结合。TestParaDefault.cpp12/19/202270类和对象2.设置参数的缺省值函数在定义时可以预先定义出形参的缺省值3.函数的重载函数的重载:出现在相同作用域的两个函数,如果具有相同的名字而形参表不同,则称为重载函数(overloadedfunction)。调用时,会根据不同的参数表选择对应的成员函数。重载函数,必须:函数名相同,函数的作用域相同,函数的参数个数或参数类型不同。使用重载函数时应注意:⑴只有返回值不同,不能成为重载函数。

intmax(inta,intb);doublemax(inta,intb); //错误⑵使用带缺省值的函数时,可能引发错误。如:

intmax(inta,intb=0);intmax(intc);当用一个实参调用该函数时,如max(2),则会出现调用歧义性12/19/202271类和对象3.函数的重载函数的重载:出现在相同作用域的两个函数,如果构造函数和析构函数构造函数和析构函数都是类的成员函数,是特殊的成员函数,不能被调用而由系统自动调用/执行。构造函数名与类名相同;析构函数名为类名前加“~”。构造函数的功能是在创建对象时给对象分配内存空间,并可使用给定值来初始化对象。析构函数的功能是用来释放一个对象的已分配空间。并可在对象被清除前,完成一些清理工作。12/19/202272类和对象构造函数和析构函数构造函数和析构函数都是类的成员函数,是特殊对前面的日期类进行修改,并将定义存放在CDate1.h文件中。如:classCDate1

{public:CDate1(inty,intm,intd);~CDate1();voidprint();private:intyear,month,day;

};函数名与类名一致,无类型但可有参数名字与类名一致,前有~,无类型无参数12/19/202273类和对象对前面的日期类进行修改,并将定义存放在CDate1.h文件中CDate1::CDate1(intm,intd,inty){month=m;day=d;year=y;cout<<"Constructorcalled.\n";}CDate1::~CDate1(){cout<<"Destructorcalled.\n";}voidCDate1::print(){cout<<year<<"."<<month<<"."<<day<<endl;}与其他成员函数定义一样,两种函数的定义可放在类体内,也可放在类体外12/19/202274类和对象CDate1::CDate1(intm,intd,int#include<iostream.h>#include"CDate1.h"voidmain(){CDate1today(2007,4,1),tomorrow(2007,4,2);cout<<"todayis";today.print();cout<<"tomorrowis";tomorrow.print();}执行程序后,输出结果为:函数结束时,自动调用析构ConstructorCalled.ConstructorCalled.todayis2007.4.1tomorrowis2007.4.2Destructorcalled.Destructorcalled.12/19/202275类和对象#include<iostream.h>函数结束时,自动调构造函数的特点有:程序中一般不直接调用构造函数,在创建对象时系统自动调用构造函数。构造函数可以重载,即可定义多个参数个数不同的函数构造函数有隐含的返回值,并由系统内部使用析构函数的特点有:一个类中只能定义一个析构函数,即不能重载析构函数可以被调用,也可系统调用被自动调用的情况有两种:在一个函数体内定义的一个对象,当函数结束时用new运算符动态创建的一个对象,在使用delete释放时12/19/202276类和对象构造函数的特点有:12/16/202228类和对象缺省构造函数和缺省析构函数在类定义中可以不定义任何构造函数,这时编译器会自动生成一个不带参数的缺省构造函数。其格式为:

<类名>::<缺省构造函数名>(){}则在程序中定义一个对象而未指明初始化时,编译器便按缺省构造函数来初始化该对象。若定义了构造函数,则编译器就不会再生成缺省构造函数,必须使用定义的构造函数创建对象。同理,若一个类中未定义析构函数,编译系统也生成一个缺省析构函数。其格式为:<类名>::~<缺省析构函数名>(){}这也是前面的程序中可以没有构造和析构函数的原因12/19/202277类和对象缺省构造函数和缺省析构函数在类定义中可以不定义任何构造函数,classCConstruct{ public:CConstruct(intx,inty);CConstruct(); voidprint(); private: intm1,m2;};CConstruct::CConstruct(intx,inty){ m1=x; m2=y;}CConstruct::CConstruct(){ m1=0; m2=0;}TestConsOverLoad.cpp例:12/19/202278类和对象classCConstructTestConsOverLovoidCConstruct::print(){cout<<m1<<","<<m2<<endl;}voidmain(){ CConstructc2; CConstructc1(3,4);c1.print();}不带参数创建对象,调用无参构造函数12/19/202279类和对象voidCConstruct::print()不带参数创拷贝初始化构造函数构造函数除可以用基本数据类型初始化对象外,还可以使用已存在的同类型的对象即类类型的对象来初始化正在创建的对象。为此,必须在类中定义一个特殊的构造函数来完成这个工作,这个构造函数被称为拷贝初始化构造函数。格式为:<类名>::<拷贝初始化构造函数名>(<类名>&<引用名>){…}如:student::student(student&s){…}每个类中必须有一个。若类中未说明,则编译系统会自动生成缺省函数。12/19/202280类和对象拷贝初始化构造函数构造函数除可以用基本数据类型初始化对象外,classCMyClass{ public: CMyClass(intx); CMyClass(CMyClass&c); private: intmember;};CMyClass::CMyClass(intx){member=x;}CMyClass::CMyClass(CMyClass&c){ cout<<"copyconstructorcalled"<<endl; member=c.member;}拷贝初始化构造函数TestCopyConstructor.cpp12/19/202281类和对象classCMyClass拷贝初始化构造函数TestCo拷贝初始化构造函数被自动调用有三种情况:一、是用一个已知对象初始化一个新对象时。二、是以值调用方式向一个函数传递对象参数时。三、当对象作为函数返回值时。CMyClassfun(CMyClassd);voidmain(){ CMyClassb(3);

CMyClassc(b); CMyClasss=fun(c);}CMyClassfun(CMyClassd){ returnd;}12/19/202282类和对象拷贝初始化构造函数被自动调用有三种情况:12/16/2022内存解析member:3bMyClass(intx)MyClass(MyClass&c)cmember:3member:3dmember:3*member:3s12/19/202283类和对象内存解析member:3bMyClass(intx)MyC对象数组对象数组:一个数组中的每个数组元素都为同一类的对象。对象数组的定义有以下几种形式:类中只有无参的构造函数类名数组名[常量表达式];例:CDate2objArray[4];类中只有需要参数的构造函数类名数组名[常量表达式]={构造函数名(参数表),…,构造函数名(参数表)};例:CDate2objArray[2]={CDate1(2002,3,4),CDate1(2008,5,26)};类中有无参的构造函数和有参的构造函数12/19/202284类和对象对象数组对象数组:一个数组中的每个数组元素都为同一类的对访问数组元素对象的成员objArray[1].print()或(objArray+1)->print()testObjectArray.cpp12/19/202285类和对象访问数组元素对象的成员testObjectArray.cpp每一个类的非静态成员函数中的都有一个指针形参this,用于指向正在操作该成员函数的对象。例如:classCDate3{ public: CDate3(inty,intm,intd); voidprint(CDate3*t); voidprint(); private: intyear,month,day;};CDate3::CDate3(inty,intm,intd){ year=y;month=m; day=d;}this指针testThis.cpp12/19/202286类和对象每一个类的非静态成员函数中的都有一个指针形参this,用于voidCDate3::print(CDate3*t){cout<<t->year<<"."<<t->month<<"."<<t->day<<endl;}voidCDate3::print(){cout<<this->year<<"."<<this->month<<"."<<this->day<<endl;}#include<iostream.h>#include"CDate3.h"voidmain(){ CDate3objThis(2008,4,23);objThis.print(&objThis);objThis.print();}隐含的指针形参this12/19/202287类和对象voidCDate3::print(CDate3*t)隐静态成员定义类时,可用关键字static声明的数据成员或成员函数称为静态成员,包括静态数据成员和静态成员函数。静态数据成员是在编译时被创建,与对象是否存在无关,其内存空间为数据区,其生命期一直到程序结束。静态数据成员必须在类外初始化:

数据类型类名::成员名=初始值;静态成员函数属于类,而不是对象成员(无this指针用来存放对象的地址),不能直接引用具体对象中的非静态成员。须使用(对象名.成员名)来引用。可以通过对象名或类名来访问静态成员。12/19/2022

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论