C++程序设计.ppt
Visual C+程序设计,2,内容安排,课程要求,3,第1章 c+基础,面向对象的程序设计,面向过程的程序设计,OOP,4,面向过程的程序设计,在以过程为主的程序设计中,问题被看作一系列需要完成的任务,而函数是用于完成这些任务的主要手段。,5,面向过程的程序设计,轮胎,车门,生产汽车,6,面向过程的程序设计,7,对象是进行活动的基本单位。,谁干什么?,面向对象的程序设计,谁什么时间干什么?,8,对象是进行活动的基本单位。,谁干什么?,面向对象的程序设计,9,面向对象的程序设计举例,居委会大扫除,一家人生活在一起,与外界相对独立。,10,面向对象的程序设计举例,生产汽车,材料、机器和工人,做什么,车 间,黑箱,11,对象是进行活动的基本单位。,数据,操作代码,对 象,对象由数据和操作码组成,面向对象的程序设计,12,面向对象的程序设计,世界是独立对象的集合,在程序中,对象是程序的基本元素。,13,小结:什么是对象?,每一个实体都是对象,14,二、类,有一些对象是具有相同的结构和特性的。,每个对象都属于一个类型。,类是对象的抽象。而对象是类的具体实例。,如同结构体类型和结构体变量,C+暂时理解成带“类”的C。,15,类是什么?,类是用来描述具有相同属性和方法的对象的集合,它定义了该集合中每个对象所共有的属性和方法。,16,()抽象与封装抽象是对具体对象(问题)进行概括,抽出这一类对象的公共性质并加以描述的过程先注意问题的本质及描述,其次是实现过程或细节数据抽象:描述某类对象的属性或状态(对象相互区别的物理量)代码抽象:描述某类对象的共有的行为特征或具有的功能。,类,17,抽象实例1钟表,数据抽象 int Hour,int Minute,int Second代码抽象 SetTime(),ShowTime(),18,抽象实例2人,数据抽象 char*name,char*sex,int age,int id代码抽象 生物属性角度:GetCloth(),Eat(),Step(),社会属性角度:Work(),Promote(),注意:同一问题可能有不同的抽象结果根据解决问题的要求不同,产生的抽象成员可能不同。,19,抽象实例3圆?,数据抽象 float radium;代码抽象 float Area();float Fence();,20,通过类的声明来实现抽象:,21,类是什么?,类是用来描述具有相同属性和方法的对象的集合,它定义了该集合中每个对象所共有的属性和方法。,22,class/声明部分private:public:protected:;/实现部分,类是什么?,23,类是什么?钟表的例子,class Clock public:void SetTime(int NewH,int NewM,int NewS);void ShowTime();private:int Hour,Minute,Second;;,24,练习1,要计算一个盒子的体积,请写出关于盒子的类,class CBoxprivate:int height,width,depth;public:CBox(int ht,int wt,int dt)height=ht;width=wt;depth=dt;int volume()return height*width*depth;,25,练习2,要计算一个圆的面积,请写出关于圆的类,#include class Circleprivate:int r;public:void Area()cout3.1415926*r*rendl;void Init(int n)r=n;,26,(2)继承与派生,保持已有类的特性而构造新类的过程称为继承;在已有类的基础上新增自己特性而产生新类的过程称为派生;被继承的已有类称为基类(或父类);派生出的新类称为派生类。,目的:继承的目的:实现代码的重用;派生的目的:当新的问题出现时,原有程序无法解决(或不能完全解决)时,需要对原有程序进行改造。,27,(3)多态,对于相同的消息,不同的对象具有不同的反应能力。多态机制使具有不同内部结构的对象可以共享相同的外部接口,通过这种方式减少代码的复杂度。,28,小结,面向对象的程序设计的主要特征:封装继承多态,面向对象的程序是由对象组成的,对象是类的实例,类之间存在着继承与派生,因此在做c+面向对象设计时,首先设计类,定义类的属性和方法,然后设计使用这些类的对象的程序。从低级到高级的处理过程,也就是自下向上的编程方式。,29,第1章 c+基础,1.1概述,30,31,头文件,标准方式 系统提供并放到指定子文件夹中;用户方式“iostream.h”这种方式下,系统先在用户当前文件夹中查找,找不到再按标准方式查找.一般来说,用包含编译器自带的头文件,用”iostream.h”来包含用户自己编写的头文件,32,补充1:引用(&),是为对象取一个别名,不占存储空间.声明一个引用的时候,必须同时对它进行初始化,使指向一个已存在的对象int a=5;int 引用经常用做函数的形参,33,例1:求圆的面积,r,34,/*第一个简单的C+程序*/#include int main()double r,area;coutr;area=3.14159*r*r;cout圆的面积为:arean;return 0;,求圆的面积,35,不同字体表示不同含义,36,37,/*第一个简单的C+程序*/#include int main()double r,area;coutr;area=3.14159*r*r;cout圆的面积为:arean;return 0;,求圆的面积,38,#include class Circleprivate:int r;public:void Area()cout3.1415926*r*rendl;void Init(int n)r=n;void main()Circle cir;cir.Init(10);cir.Area();,用类重写求圆的面积,这里可否把类定义成只有一个公有的成员函数Area(int r)呢?如果可以,程序应该怎样写?,39,例2:在屏幕上输出下面图形,*,40,#include int main()int num=5;for(int i=0;i num;i+)for(int j=0;j=i;j+)cout*;cout n;return 0;,不用函数打印输出,41,去掉返回值,#include void main()int num=5;for(int i=0;i num;i+)for(int j=0;j=i;j+)cout*;cout n;,42,用函数打印输出,/输出星号的三角形阵列#include void DoDraw(int num);/声明一个全局函数int main()int num=5;/定义并初始化变量DoDraw(num);/函数的调用return 0;/指定返回值void DoDraw(int num)/函数的定义for(int i=0;i num;i+)/循环语句for(int j=0;j=i;j+)cout*;cout n;,43,用类打印输出,#include class CDrawArraypublic:void DoDraw(int num);void CDrawArray:DoDraw(int num)for(int i=0;inum;i+)for(int j=0;j=i;j+)cout*;coutn;void main()int num=5;CDrawArray myDraw;myDraw.DoDraw(num);,这里可否把DoDraw成员函数的实现放到类内来使用呢?如果可以,怎样写?,44,钟表的例子,class Clock public:void SetTime(int NewH,int NewM,int NewS);void ShowTime();private:int Hour,Minute,Second;;,45,void Clock:SetTime(int NewH,int NewM,int NewS)Hour=NewH;Minute=NewM;Second=NewS;Void Clock:ShowTime()coutHour“:”Minute“:”Second;,46,1.2.1关于类的几点说明,(1)类中的数据成员的数据类型可以是任意的,包含整型、浮点型、字符型、数组、指针和引用等,也可以是另一个类的对象。例如:class COne;class CTwo private:COne a;/数据成员a是已定义的COne类对象;,47,1.2.1关于类的几点说明,(2)由于类是一种数据类型,系统并不会为其分配内存空间,所以在定义类中的数据成员时,不能对其进行初始化,也不能指定除static之外的任何存储类型。例如类CStuscore中,下面的定义是错误的:class CStuscore private:floatfScore3=80.0,90.0,78.0;/错误:不能在直接对数据成员进行初始化 auto int n;/错误:不合法的存储类型;,48,1.2.1关于类的几点说明,(3)访问权限关键词public、private、protected在类中使用先后次序无关紧要,且可使用多次。每个访问权限关键词为类成员所确定的访问权限是从该关键词开始到下一个关键词为止。如在CStuscore类中,私有数据成员是用两个private来分开写成二个部分。同样,若将公有成员函数用两个public分开写成二个部分,仍是正确的。,49,1.2.1关于类的几点说明,(4)在进行类设计时,通常将数据成员的声明为私有的,而将大多数成员函数声明成公有的。这样,类以外的代码不能直接访问类的访问权限私有数据,从而实现了数据的封装。而公有成员函数可为内部的私有数据成员提供外部接口,但接口实现的细节在类外又是不可见的,这就是C+类的优点之一。,50,1.2.1关于类的几点说明,(5)一般来说,程序员更多关心的是public成员,因此常将public成员写在类体中的前面,而将private成员写在类体中的后面。若在类体内没有指定成员的访问权限,则默认的访问权限为私有的(private)。,(6)当程序比较大时,应尽量将类单独存放在一个文件中或将类的声明放在头文件中而将成员函数的实现放在与头文件同名的.cpp文件中(这也是Visual C+6.0的编程方式)。,51,练习,请写出坐标系中一个点的类。,提示:属性就是有值和值方法有:点的初始化得到点的坐标值,52,class Pointpublic:void Init(int initX,int initY)X=initX;Y=initY;int GetX()return x;int GetY()return Y;private:int X,Y;,一个坐标点的类,53,1.2.2对象定义,类的对象是该类的某一特定实体,即类类型的变量。,类对象有3种定义方式:声明之后定义、声明之时定义和一次性定义。例如:class A;A a;/声明之后定义 class B b,c;/声明之时定义 class d,e;/一次性定义在程序中应尽量使用对象的声明之后定义方式,即按下列格式进行:,;,54,1.2.3对象访问,一个对象的成员就是该对象的类所定义的数据成员和成员函数。,那么类中的成员的访问方式又是如何的呢?,类中成员互访直接使用成员名类外访问使用“对象名.成员名”访问public属性的成员,55,class Clock public:void SetTime(int NewH,int NewM,int NewS);void ShowTime();private:int Hour,Minute,Second;;,用钟表的例子来理解对象的访问,void Clock:SetTime(int NewH,int NewM,int NewS)Hour=NewH;Minute=NewM;Second=NewS;Void Clock:ShowTime()coutHour“:”Minute“:”Second;void main(void)Clock myclock;Myclock.SetTime(8,10,30);Myclock.ShowTime();,用钟表的例子来理解对象的访问,57,结构体与类的区别?从另一角度来理解类,#include/在c+中实现结构体struct Cpoint int x;int y;void main()Cpoint pt;pt.x=3;pt.y=6;coutpt.xendl;coutpt.yendl;,58,#include struct Cpointint x;int y;void show()coutxendl;coutyendl;void main()Cpoint pt;pt.x=3;pt.y=6;pt.show();,看c+中的结构体和c中结构体有何区别?,59,#include class Cpointpublic:int x;int y;void show()coutxendl;coutyendl;void main()Cpoint pt;pt.x=3;pt.y=6;pt.show();,比较类与结构体,60,在c中,定义一个结构体变量要如下:struct Cpoint pt;而在c+中,定义个结构体变量,可以省略struct。直接 Cpoint pt;,结构体与类的区别?从另一角度来理解类,在c中,结构体中不可以加函数;而在c+中,结构体中可以加函数。,将struct Cpoint换成class Cpoint,并且在类中加入public之后,程序功能是一样的,61,这说明在struct之中默认的成员变量和函数是public的,而在类中是private的.访问权限不同.,结构体与类的区别?从另一角度来理解类,这也就更好的说明的使用类可以更好地保证数据的安全性,当然这个程序也说明了struct和class的相似,可以认为类是一种特殊的结构体.,62,class Cpointpublic:int x;int y;void show()coutxendly;,类的写法举例,class Cpointprivate:int x;int y;public:void show()coutxendly;,63,#include class Cpointint x;int y;public:void show()coutxendl;coutyendl;void init(int a,int b)x=a;y=b;void main()Cpoint pt;pt.init(3,6);pt.show();,64,1.2.4构造函数对象的初始化,由于类的封装性,不能像普通变量一样初始化,65,#include class pointint x;int y;public:void show()coutxendl;coutyendl;void init(int a,int b)x=a;y=b;void main()point pt;pt.init(3,6);pt.show();,#include class Cpointpublic:void show()coutxendlyendl;Cpoint(int a,int b)x=a;y=b;private:int x;int y;void main()Cpoint pt(3,5);pt.show();,66,1.2.4构造函数对象的初始化,虽然构造函数的定义方式与一般成员函数没有什么区别,但要注意:构造函数名必须与类同名。只有约定了构造函数名,系统在生成类的对象时,才能自 动调用类的构造函数。Cpoint pt(3,5);,67,定义的构造函数不能指定其返回值的类型,也不能指定为void 类型。事实上,由于构造函数主要用于对象数据成员的初始化,因而无须返回函数值,也就无须有返回类型。,1.2.4构造函数对象的初始化,Cpoint(int a,int b)x=a;y=b;,68,若要用类定义对象,则构造函数必须是公有型成员函数,否则类无法实例化。若类仅用于派生其它类,则构造函数可定义为保护型成员函数。,1.2.4构造函数对象的初始化,对象的访问权限问题:保护类的成员在外部无法访问,69,1.2.4构造函数对象的初始化,当构造函数重载以及设定构造函数默认形参值时,要避免出现二义性。,#include class Cpointpublic:void show()coutxendlyendl;Cpoint(int a,int b)x=a;y=b;coutCpoint(int a,int b)was called.endl;Cpoint()coutCpoint()was calledendl;private:int x;int y;void main()Cpoint pt(3,5);pt.show();,请写出运行结果,71,构造函数可以带参数,也可以不带参数;构造函数也可以有默认的形参值,1.2.4构造函数对象的初始化,练习:求一个盒子的体积,长宽高分别为1、2、3;默认时(也就是主函数中不输入具体值),求长宽高分别为1、1、1时的体积。,72,如果没有定义任何构造函数,则编译自动为类隐式生成一个不带任何参数的默认构造函数,默认构造函数的形式如下:CPerson(),1.2.4构造函数对象的初始化,当类定义中指定了构造函数,则隐式的默认构造函数不再存在。,73,格式如下:(),1.2.5析构函数,说明如下:(1)每一个类最多只能有一个析构函数,且应为public,否则类实例化后无法自动调用析构函数进行释放,不能被重载,没有任何参数,也不返回任何值,函数名前也不能有任何关键词(包括void),74,1.2.5析构函数,(2)与类的其他成员函数一样,析构函数的定义也可在类体外进行,但必须指明它所属的类,且在类体中还必须有析构函数的声明。,(3)与默认构造函数类似,若类的声明中没有定义析构函数时,则编译也会自动生成一个隐式的不做任何操作的默认析构函数。,75,#include class Cboxpublic:void vol()cout“盒子体积为height*width*depthendl;Cbox(int x=1,int y=1,int z=1)height=x;width=y;depth=z;Cbox()private:int height,width,depth;,76,void main()Cbox thisbox(1,2,3);Cbox defaultbox;thisbox.vol();defaultbox.vol();,77,1.2.6指针,对象成员的访问 对象名-对象名-,例子见下页,78,#include class Cpointint x;int y;public:void show()coutxendl;coutyendl;void init(int a,int b)x=a;y=b;,void main()Cpoint pt;Cpoint*ptr=new Cpoint;ptr-init(8,89);pt.init(3,6);pt.show();(*ptr).show();,79,练习,一圆型游泳池,需在周围建立一圆型过道,并在其四周围上栅栏.栅栏价格为35元/米,过道造价为20元/平方米.过道宽度为3米,游泳池半径由键盘输入.要求编程计算并输出过道和栅栏的造价.,过道,80,1.2.7拷贝构造函数,拷贝构造函数是一种特殊的构造函数,其形参为本类的对象引用,作用:使用一个对象(参数指定的对象),去初始化一个正在被建立的同类型对象,class 类名 public:类名(形参);/构造函数 类名(类名 类名:类名(类名&对象名)/拷贝构造函数的实现函数体的实现,81,1.2.7拷贝构造函数,浅拷贝 仅仅是内存内容的拷贝2.深拷贝 对于数据成员有指针的情况,浅拷贝无法实现,在进行数值拷贝之前,为指针类型的数据成员另开辟一个独立的内存空间.-由于拷贝还需另开辟内存空间,称为深拷贝,82,1.2.8this指针,this指针是类中的一个特殊指针当类实例化时,this指针指向对象自己,而在类的声明时指向类本身.成员函数的参数和该类的成员变量名同名时,则必须用this指针来显式区分.,83,1.2的小结,类的声明和实现对象成员的访问构造函数和析构函数拷贝构造函数this指针new和delete,84,1.3 继承和派生,基类,派生类,继续派生,1.3.1继承的特性单向性传递性可重用性,85,1.3 继承和派生,1.3.2派生类的定义,class:,;,关于派生类的说明参见课本page21,86,访问控制,不同继承方式的影响主要体现在:派生类成员对基类成员的访问控制派生类对象对基类成员的访问控制三种继承方式公有继承私有继承保护继承 如果不说明继承方式,默认是私有继承,87,类的继承访问特性,88,公有继承,基类的public和protected成员的访问属性在派生类中保持不变,但基类的private成员不可访问。派生类中的成员函数可以直接访问基类中的public和protected成员,但不能访问基类的private成员。通过派生类的对象只能访问基类的public成员,89,class Cpointprivate:int X,Y;public:void Initp(int a,int b)X=a;Y=b;void Getxy()coutXendlYendl;,90,class CRect:public Cpointprivate:int H,W;public:void Initr(int a,int b,int c,int d)Initp(a,b);/调用基类的成员函数H=c;W=d;void GetWH()coutWendlHendl;,可否把Initp(a,b);换成 X=a;Y=b;,91,void main()CRect rect;rect.Initr(2,3,4,5);rect.Getxy();/通过派生类对象访问基类成员rect.GetWH();,92,公有继承,基类的public和protected成员的访问属性在派生类中保持不变,但基类的private成员不可访问。派生类中的成员函数可以直接访问基类中的public和protected成员,但不能访问基类的private成员。通过派生类的对象只能访问基类的public成员,93,私有继承,基类的public和protected成员都以private身份出现在派生类中,但基类的private成员不可访问。派生类中的成员函数可以直接访问基类中的public和protected成员,但不能访问基类的private成员。通过派生类的对象不能访问基类中的任何成员.,94,保护继承,基类的public和protected成员都以protected身份出现在派生类中,但基类的private成员不可访问。派生类中的成员函数可以直接访问基类中的public和protected成员,但不能访问基类的private成员。通过派生类的对象不能访问基类中的任何成员.,95,Protected成员的特点与作用,对建立其所在类对象的模块来说(水平访问时).它与private成员的性质相同。对于派生类来说(垂直访问时),它与public成员的性质相同.,96,派生类与基类的构造函数,若基类中未声明构造函数,派生类中也可以不声明,全采用缺省形式构造函数。,97,派生类与基类的构造函数,当基类中声明有缺省形式的构造函数或未声明构造函数时,派生类构造函数的声明中可以省略对基类构造函数的调用。,98,派生类与基类的构造函数,当基类声明有带形参的构造函数时,派生类也应声明带形参的构造函数,提供将参数传递给基类构造函数的途径。,99,对象成员在派生类构造函数中的初始化,派生类与基类的构造函数,100,派生类的构造函数,基类的构造函数不被继承,需要在派生类中自行声明声明构造函数时,只需要对本类中新增成员进行初始化,对继承来的基类成员的初始化由基类完成。,101,派生类的构造函数,派生类名:派生类名(基类所需的形参,本类成员所需的形参):基类名(参数)本类成员初始化赋值语句;,102,赋值兼容原则,一个公有派生类的对象在使用上可以被当做基类的对象,反之则禁止。具体表现在:派生类的对象可以被赋值给基类对象。派生类的对象可以初始化基类的引用。指向基类的指针也可以指向派生类。,103,静态联编与动态联编,联编:程序自身彼此关联的过程,确定程序中的操作调用与执行该操作的代码间的关系。静态联编(静态束定)联编工作出现在编译阶段,用对象名或者类名来限定要调用的函数。动态联编:联编工作在程序运行时执行,在程序运行时才确定将要调用的函数。,104,虚函数,在类的声明中,在函数原型之前写virtual。具有继承性,基类中声明了虚函数,派生类中无论是否说明,同原型函数都自动为虚函数。调用方式:通过基类指针或引用,执行时会根据指针指向的对象的类,决定调用哪个函数。,105,小结,封装性继承性多态性,106,第一章结束,