《类和对象》课件_第1页
《类和对象》课件_第2页
《类和对象》课件_第3页
《类和对象》课件_第4页
《类和对象》课件_第5页
已阅读5页,还剩58页未读 继续免费阅读

下载本文档

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

文档简介

《类和对象》PPT课件目录6.1类6.1.1类的定义&数据成员6.1.2类的成员函数6.1.3访问权限6.2类对象6.2.1对象的定义格式6.2.2对象成员的表示方法6.3构造函数和析构函数6.3.1构造函数6.3.2析构函数6.4常类型6.4.1常引用6.4.2常对象6.4.3常对象成员6.5静态成员6.6成员指针(略)6.7this指针6.1类从语言的角度,类是一种数据类型对象是具有这种类型的变量。类似于intn类是一种用户自定义的数据类数据成员(属性、成员变量)成员函数(服务、方法)复杂的数据类型6.1.1类的定义class<类名>{

//数据成员声明

private:

protected:

public:

//成员函数声明

private:

protected:

public:};类头每个类定义引入一个新的(类)类型类体类成员函数列表类的数据成员声明方式同普通变量的声明,可以是任意类型注!数据成员不能在类体中显式地初始化classPoint{//intx=0,y=0;错误 intx,y;};6.1.2类的成员函数成员函数的声明——在类体内

classPoint{ intx,y; //intx=0,y=0;错误

voidsetPoint(intx,inty); voidmove(intx1,inty1); voiddisplay();};成员函数的定义(1)定义在类体内在类定义体内实现的成员函数都是内联函数在类定义体外,通过声明和定义分别加上inline也是内联函数(2)定义在类体外——使用域运算符::该函数是属于哪一个类的成员函数<返回值类型><类名>::<成员函数名>(<形式参数表>){//函数体}例:类的定义#include<iostream.h>classPoint

//定义类Point{ intx,y; //数据成员-私有public: voidsetPoint(intx1,inty1){x=x1;y=y1;}//成员函数定义在类体内-内联函数1

void

move(int

x1,int

y1); voiddisplay();//内联函数2-但成员函数定义在类体外};voidPoint::move(intx1,inty1) //成员函数定义在类体外,用::{x=x+x1;y=y+y1;}inlinevoid

Point::display()//内联函数{cout<<"x="<<x<<",y="<<y<<endl;}注意:成员函数可以重载,但一个成员函数只能重载自己类中的其它成员函数。成员函数的参数可以有默认值。在类体中定义的成员函数都是内联函数。在类体外定义的成员函数缺省不是内联的,也可通过在函数的声明和定义上分别加inline表示该函数是内联的。6.1.3访问权限c++允许类的数据成员或成员函数有不同程度的可见性private:(私有的)只允许类本身的成员函数和友元类的成员函数)对其访问其他任何函数都不能访问(包括其他类和派生类的成员函数)即便是本类的对象也不能访问私有成员public:(公有的):类与外部的接口,任何外部函数都可访问公有成员变量和成员函数也可以通过本类的对象来访问!protected:(保护的)用于类的继承与private类似,类的成员函数和友元类的成员函数可以访问该类的派生类的成员也可以访问类成员缺省为私有的!!类vs.结构:类和struct的每个方面都是一样的,只是class中的成员默认为私有的,而struct中的成员默认为公有的。类的封装性数据成员可只在类内被处理,也可开放给外界,以数据封装的目的而言,自然是前者较为妥当,但有时也不得不开放。displaysetvalueXY…类Pointmove外部

成员函数内部数据成员include<iostream.h>classPoint{

private:

intx,y; //数据成员

public:voidsetPoint(intx1,inty1){x=x1;y=y1;}

void

move(int

x1,int

y1); //成员函数

voiddisplay(); //成员函数

};void

Point::

move(int

x1,int

y1){x=x+x1;y=y+y1;}voidPoint::display(){cout<<“x=“<<x<<“,y=“<<y<<endl;}类成员函数可直接访问类的数据成员6.2类对象类只是一个数据类型。使用类必须说明类的对象。数据类型

变量类

对象定义类时,系统是不会给类分配存储空间的。只有定义类对象时会引起内存分配。6.2.1对象的定义格式

定义对象:<类名><对象名表>;PointmyPoint1,myPoint2;引起内存分配,每个对象有自己的类数据成员拷贝一个对象可以被同一类型的另一个对象初始化或赋值。myPoint2=myPoint1;缺省情况下,拷贝一个类对象与拷贝它的全部数据成员等价对象数组的声明:Point

myptarray[3];类对象的指针和引用的声明:Point

myPoint1,*myPoint2,*myPoint3;myPoint2=&myPoint1;myPoint3=myPoint2;

xyxymyPoint1myPoint2对象的创建方式静态创建Pointaa;动态创建Point*bb=new

Point;Point*p;只定义一个指针(指向Point类型对象的指针),但并没有真正创建对象Point*p=newPoint;使用newPoint建立了一个临时对象,并使指针p指象该对象Point*p=NULL;p=&aa;p=newPoint;6.2.2对象成员的表示方法对象成员有数据成员和成员函数.必须用成员访问操作符来访问类对象成员成员访问操作符(.):与类对象或引用连用箭头成员访问操作符(->):与类对象的指针连用一般对象的成员表示如下:<对象名>.<数据成员名><对象名>.<成员函数名>(<参数表>)指向对象的指针的成员表示如下:<对象指针名>-><数据成员名><对象指针名>-><成员函数名>(<参数表>)注:

<对象指针名>-><成员名>等价于(*<对象指针名>).<成员名>voidmain(){samplea;a.y=5;//合法a.x=5;

//错误!对象不能访问类的 //私有变量xa.z=5;//错误!不能访问保护变量za.setx(5);a.sety(5);sample*p=0;p=&a;p->x=4;

//错误!私有变量xp->setx(6);inti;i=(*p).abs(-7);}例:class

sample{

private:

intx;

protected:

intz;public:

inty;public:

voidsetx(intx);

voidsety(intx);

intabs(intx);

intgetx(){returnx;}

intgetz(){returnz;}

//类的成员函数可以访问//类的私有变量,保护变量

}//文件main.cppinclude<iostream.h>classPoint{private:intx,y;public:voidsetPoint(intx1,inty1){x=x1;y=y1;}

void

move(int

x1,int

y1);voiddisplay();};void

Point::

move(int

x1,int

y1){x=x+x1;y=y+y1;}voidPoint::display(){cout<<“x=“<<x<<“,y=“<<y<<endl;}例:从绘图的角度看一个点,把它看作一个对象voidmain(){

Pointa;

Point*p=newPoint;

a.setPoint(12,6);a.move(3,4);cout<<“Firstpoint=>”;

a.display();

p->setPoint(5,12);p->move(3,4);cout<<”Sencondpoint=>”;

p->display();

deletep;}Firstpoint=>(15,10)Secondpoint=>(8,16)6.3构造函数和析构函数构造函数和析构函数都是类的成员函数,但他们是特殊的成员函数不用调用便自动执行名字与类的名字基本相同.6.3.1构造函数问题:类的数据成员如何初始化?

因为类定义体中不能在定义时初始化数据成员解决:利用类的构造函数来初始化类的数据成员.构造函数构造函数是类的一个特殊成员函数它与类同名,没有返回值创建类的对象时,编译器会自动调用类的“构造函数”classSample{public: Sample(<参数表>);};Sample::Sample(<参数表>){}//在构造函数中可以执行初始化成员变量的操作。[例6.4]#include<iostream.h>classPoint{

public:

Point(intx1,inty1){x=x1;y=y1;}//构造函数

voiddisplay(){cout<<”(“<<x<<”,”<<y<<”)”<<endl; }...

private:intx,y;};voidmain(){

Pointa(12,6),Point*p=newPoint(5,12);

cout<<”Firstpoint=>”;a.display();cout<<”Sencondpoint=>”;p->display();

deletep;}Firstpoint=>(12,6)Secondpoint=>(5,12)默认构造函数若一个类没有定义构造函数,编译器会自动生成一个不带参的构造函数,——默认构造函数程序中定义一个对象而没有指明初始化时,编译器便按默认构造函数来初始化该对象。class

Point{public:

Point(){} ...}构造函数可以象普通函数一样被重载C++根据说明中的参数个数和类型选择合适的构造函数.6.3.2重载构造函数[例6.5]重载构造函数#include<iostream.h>classPoint{ public:

Point(){x=0;y=0;} Point(intx1,inty1){x=x1;y=y1;} voidsetvalue(intx1,inty1){x=x1;y=y1;} voiddispoint(){ cout<<”(“<<x<<”,”<<y<<”)”<<endl;}private:intx,y;};voidmain(){

Pointa(12,16),b; cout<<”Firstpoint=>”;a.dispoint();cout<<”Secondpoint=>”;b.dispoint();}运行结果:Firstpoint=>(12,6)Secondpoint=>(0,0)拷贝(初始化)构造函数用同类型的其他已知对象初始化本对象。拷贝构造函数的格式:

Point(constPoint&point1)将已知对象的数据成员的值拷贝给正在创建的同类的对象.const是一个类型修饰符,被它修饰的对象是一个不能被更新的常量.[例6.6](运行)#include<iostream.h>classPoint{public:Point(intx1,inty1){x=x1;y=y1;}Point(constPoint&obj);voiddisplay(){ cout<<"("<<x<<","<<y<<")"<<endl;}private:intx,y;};Point::Point(constPoint&obj){x=obj.x;y=obj.y;cout<<"拷贝构造函数调用"<<endl;}voidmain(){Pointa(12,16);Pointb(a);Pointc=a;cout<<"b=>";b.display();cout<<"c=>";c.display();}小结每个类都必须有一个拷贝初始化构造函数.如果没有说明,则编译系统自动生成一个具有上述形式的默认拷贝初始化构造函数.为什么要自己创建?是否需要拷贝所有的数据成员?是否要做其他的事情?数据成员中有指针类型时,默认的拷贝构造函数实现的是浅拷贝,浅拷贝会带来安全上的隐患?对象消失时应做一些扫尾工作?一个类的对象在生命期间分配了资源,这些资源需要在对象不复存在以前被释放.(例如,如果构造函数中动态分配了内存,这块内存在对象消失之前必须被释放.)与构造函数对应的是析构函数,当一个对象消失,系统自动调用类的析构函数。6.3.2析构函数

析构函数的格式

~类名没有参数没有返回值.一个类中只能定义一个析构函数,所以析构函数不能重载。析构函数在对象生命期结束时被编译器自动调用。classSample{intx,y;public:Sample();Sample(intx,inty);//可以有参,无返回值,可重载

~Sample();//无参,无返回值,不可重载}析构函数一般做一些清除工作,C++中,清除同初始化一样重要。通过析构函数来保证执行清除.#include<iostream.h>#include<string.h>classPoint{private:intx,y;

char*m_name;public:Point(intx1,inty1,constchar*name){x=x1;y=y1;

m_name=newchar[10];strcpy(m_name,name);}

~Point(){delete[]m_name;cout<<"调用析构函数"<<endl;}voiddisplay(){cout<<m_name<<“:("<<x<<","<<y<<")"<<endl;}};voidmain(){

Pointa(12,6,"测点1");Point*p=newPoint(5,12,"测点2");cout<<"Firstpoint=>";a.display();cout<<"Secondpoint=>";p->display();

deletep;}结果:Firstpoint=>测点1:(12,6)Secondpoint=>测点2:(5,12)调用析构函数.调用析构函数[修改例6.7析构函数]

同默认构造函数一样,如果一个类没有定义析构函数,编译器会自动生成一个,其格式如下:<类名>::~<默认析构函数名>(){}默认析构函数是一个空函数。classPoint{private:intx,y;public:Point(intx1,inty1){x=x1;y=y1;}

~Point(){}}默认析构函数构造函数和析构函数没有返回值。执行特定功能这与返回值为void的函数显然不同。后者虽然也不返回任何值,但我们还可以让它做点别的。而构造函数和析构函数则不允许.在程序中创建和消除一个对象的行为非常特殊,就象出生和死亡,而且总是由编译器来调用这些函数以确保它们被执行。如果他们有返回值,要么编译器必须知道如何处理返回值,要么就只能由用户自己来显式地调用构造函数与析构函数,就破坏了安全性.类的组合-例:点-线类,计算两点间线段距离#include<iostream.h>classPoint{private: intx,y;public: Point(intx1=0,inty1=0){x=x1;y=y1;} Point(constPoint&p){x=p.x;y=p.y;} intgetx(){returnx;} intgety(){returny;}};classLine{private: Pointp1,p2;public: Line(constPoint&p1,constPoint&p2); doubledistance();};Line::Line(constPoint&pt1,constPoint&pt2) :p1(pt1),p2(pt2){//或p1=pt1;//p2=pt2;}doubleLine::distance(){ doubledx=p2.getx()–p1.getx(); doubledy=p2.gety()–p1.gety(); return(sqrt(dx*dx+dy*dy));}voidmain(){ Pointp1(3,4),p2(4,5); Linel(p1,p2); cout<<l.distance()<<endl;}问题:如何既保证数据共享又防止改变数据?常类型——const说明的类型常类型的变量或对象的值是不能更新的常类型包括:常引用常对象常对象成员.6.4常类型const说明引用时用const修饰,则被说明的引用为常引用。const<类型说明符>&<引用名>;常引用所引用的对象不能被更新。如果用常引用做形参,便不会意外地发生对实参的更改。引用:inti=10; int&n=i;n=123;常引用:

constint&n=i; n=123//错误6.4.1常引用[例6.8常引用]#include<iostream.h>intadd(constint&x,constint&y);voidmain(){ inti=10,j=20; cout<<i<<”+”<<j<<”=”<<add(i,j)<<endl;}//常引用做形参,在函数中不能更新所引用的对象,对应的实参不会被破坏intadd(constint&x,constint&y){ //x++;y++;错误!returnx+y;}#include<iostream.h>classPoint{private:intx,y;public: Point(intx1,inty1){x=x1;y=y1;}

Point(constPoint&obj);voiddisplay(){ cout<<”(“<<x<<”,”<<y<<”)”<<endl;}};Point::Point(constPoint&obj){x=obj.x;y=obj.y;}上节例子:Point类中使用的常引用即对象常量,定义:<类名>const<对象名>;或const<类名><对象名>;constinti=10;//常量必须初始化constPointp(1,2);常对象也是值(对象的数据成员)不能改的变量。改变对象数据成员的可能方式?6.4.2常对象class

Cloth{private:

intID;//条形码public:

intsize;//服装尺寸public: Cloth(intid,ints){ ID=id;size=s; } voidprint(){cout<<"ID="<<ID<<endl;}

//voidprint()const{cout<<"ID="<<ID<<endl;}};voidmain(){constClotha(200593000,165);//常对象样品为0号cout<<a.size<<endl;

//a.size=2;错!常对象不能更新数据成员的值 //a.print();错!常对象不能调用一般的成员函数}例:常对象(Cloth类)-修改的例6.9错!常对象不能更新数据成员的值错!常对象不能调用一般的成员函数常对象能直接读出public变量的值,private变量的值咋办?没有公共接口呀?——常成员函数:)6.4.2常对象成员-const修饰的类成员常成员函数常数据成员1.常成员函数const说明的函数为常成员函数<类型><函数名>(<参数表>)const;注意const是函数类型的一个组成部分,因此函数声明、实现部分都要带const关键词。常成员函数不能更新数据成员,也不能调用该类中没有用const修饰的成员函数.常对象只能调用它的常成员函数,而不能调用其他成员函数.能够区分重载函数。

voidprint(); voidprint()const;//则这是对print的有效重载.class

Cloth{private:

intID;//条形码public:

intsize;//服装尺寸public: Cloth(intid,ints){ ID=id;size=s; } voidprint(){cout<<"ID="<<ID<<endl;} //voidprint()const{cout<<"ID="<<ID<<endl;}};voidmain(){constClotha(2005000,165);//常对象样品为0号Clothb(20050003,175);

//cout<<a.size<<endl;b.print();//调用voidprint() //a.print();错!常对象不能调用一般的成员函数}例:常成员函数-修改Cloth类

参考例6.10voidprint()const{cout<<"ID="<<ID<<endl;}a.print();//对!调用voidprint()const常对象能调用常成员函数ID=2005003ID=2005000

象一般数据一样,类的数据成员也可以是常量问题:一个对象从创建开始存在期间都不变的一些数据?如ID?常数据成员使用const说明的数据成员.常数据成员的初始化构造函数只能通过初始化列表对类中的常数据成员进行初始化.程序代码中构造函数Sample的格式如下:Sample(intid):n(id){}

2.常数据成员class

Cloth{private:constintID;//条形码——常数据成员public:

intsize;//服装尺寸——普通数据成员public: Cloth(intid,ints){ ID=id;size=s; }

voidprint(){cout<<"ID="<<ID<<endl;} voidprint()const{cout<<"ID="<<ID<<endl;}};voidmain(){constClotha(2005000,165);//常对象样品为0号

Clothb(2005003,175);Clothc(2005004,175);

a.print();//调用voidprint()constb.print();//调用voidprint()c.print();}constintID;//条形码——常数据成员例:给Cloth类加上常数据成员Cloth(intid,ints):ID(id),size(s){

}初始化列表冒号后是一个数据成员初始化列表,初始化项——数据成员名(初始值)多个初始化项时,要用逗号隔开.也适用于普通成员变量问题:同一个类的不同对象之间如何共享数据和函数?classPoint{ intx,y;intcountP;//所建立的点对象的个数?}静态成员:静态数据成员静态成员函数.6.5静态成员

静态数据成员不属于任何一个具体的对象,而是类的所有对象共享的数据成员定义:在类体内定义static数据成员初始化:必须在类体外初始化。(不能在构造函数中初始化!)静态数据成员不属于任何一个对象,所以必须初始化!<类型><类名>::<静态数据成员>=<值>;

引用<类名>::<静态数据成员>访问权限——同普通数据成员私有的一样不能被外部访问静态数据成员可以由任意访问权限许可的函数访问(如:类的成员函数)。6.5.1静态数据成员[例6.12静态数据成员]#include<iostream.h>classSample{intn;public:Sample(inti){n=i;}voidadd(){s+=n;}

staticints;};intSample::s=0;voidmain(){Samplea(2),b(5),c(8);a.add();cout<<”s=”<<Sample::s<<endl;//a.sb.add();cout<<”s=”<<Sample::s<<endl;//a.s}结果:s=2s=7静态数据成员的定义——在类体内!静态数据成员必须初始化——在类体外!静态数据成员的使用——用类名#include<iostream.h>classPoint{private: intx,y;

staticintcountP;public:

Point(intx1=0,inty1=0){x=x1;y=y1;

countP++;}

Point(constPoint&p){x=p.x;y=p.y;} intgetx(){returnx;} intgety(){returny;}intgetcountP(){returncountP;}};intPoint::countP=0;voidmain(){Pointp1(1,2);Pointp2(3,4);cout<<p1.getcountP()<<endl;cout<<p2.getcountP();}例:所创建的Point对象的个数结果:22只想用类的成员函数却不想创建对象,行不?只想得到点的个数(静态成员变量),不想使用具体的对象,可以不?只要类存在,不用定义对象,就可以使用静态成员函数定义static类型<静态成员名>(<函数表>);调用

<类名>::<静态成员名>(<函数表>);6.5.2静态成员函数静态成员函数只能访问该类的静态数据成员、静态成员函数和类以外的函数和数据,不能访问类中的非静态数据成员(因为非静态数据成员只有对象存在时才有意义)。和一般成员函数类似,静态成员函数也有访问限制,private静态成员函数不能由外界访问。但静态数据成员和静态成员函数可由任意访问权限许可的函数访问。注意:静态成员函数[例6.13静态成员函数]

#include<iostream.h>ints=0;classSample{private:

staticintn;public: Sample(inti){n=i;}

staticvoidadd(){s+=n;}};intSample::n=0;voidmain(){ Samplea(2),b(5);

Sample::add();cout<<”s=”<<s<<endl;}运行结果s=5#include<iostream.h>classPoint{private: intx,y;

staticintcountP;public:

Point(intx1=0,inty1=0){x=x1;y=y1;

countP++;}

Point(constPoint&p){x=p.x;y=p.y;} intgetx(){returnx;} intgety(){returny;}intgetcountP(){returncountP;}};intPoint::countP=0;voidmain(){Pointp1(1,2);Pointp2(3,4);cout<<p1.getcountP()<<endl;cout<<p2.getcountP();}例:所创建的Point对象的个数

——使用类静态成员函数结果:2staticintgetcountP(){returncountP;}cout<<Point::getcountP();在C++中,除了可以定义指向对象的指针外,还可以定义指向类成员的指针。包括类数据成员指针和类成员函数指针。6.6成员指针(本节略)定义格式:<类型><类名>::*<指针名>初始化与赋值:

6.6.1类数据成员指针intm,n=10;int*p;p=&n;intSample::*p;p=&Sample::m;p=&Sample::n;classSample{public: intm,n;}引用其值: 由于类不是在运行时存在的对象,因此在使用类数据成员指针时,需要首先指定类的一个数据成员,然后通过类的对象来引用指针所指向的成员。[例6.

14类数据成员指针]#include<iostream.h>ints=0;classSample{public: voiddisp(){ cout<<”m=”<<m<<endl; cout<<”n=”<<n<<endl; }; intm,n;};voidmain(){ intSample::*p=&Sample::m; Samplea;a.*p=10;//a.m=10;

p=&Sample::n;

a.*p=20;//a.n=20;

a.disp();}运行结果:m=10n=20:程序中类Sample的m和n数据成员必须具有相同的数据类型(这里均为int),而且仅当为public时才能这样使用。为什么,请大家思考。注意指向类成员函数指针的定义:<类型>(<类型>::*<指针名>)(<参数表>)给类成员函数指针赋值的格式如下:<指向函数的指针名>=<函数名>程序中使用指向指针调用函数的格式如下:(*<指向函数的指针名>)(<参数表>)6.2.2类成员函数指针[例6.15类成员函数指针]#include<iostream.h>ints=0;classSample{public:voidsetm(inti){m=i;

温馨提示

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

评论

0/150

提交评论