《面向对象程序设计C++课件》由会员分享,可在线阅读,更多相关《面向对象程序设计C++课件(150页珍藏版)》请在金锄头文库上搜索。
1、第一章 面向对象及C+基础知识一、面向过程与面向对象C+的历史 Simula67、Ada、CPL、 BCPL、B语言、C语言、带类的C、C+机器语言汇编语言高级语言自然语言面向对象面向过程抽象:一组对象的共同特征抽象为类。封装:将一组数据及其相关的操作集合在一起。Like a 饮料机。继承:一个对象可以获得其他对象的特征。多态性:不同对象调用相同的接口,但结果不同。二、面向对象程序设计方法三、C+新的风格(1/5)输入/输出scanf(“%d”,&i)ciniprintf(“%d”,i)couti 不需要记格式说明符,不需要记格式说明符,C+C+根据数据根据数据类型自动匹配。类型自动匹配。三、
2、C+新的风格(2/5)灵活的注释 couti;/输出i的值新的换行符 couti#define max(x,y) xy?x:yy?x:yinlineinline intint max(intmax(int x,intx,int y) y) return return xxy?x:yy?x:y; ; 可以在编译时做数据类型的校验,避免隐可以在编译时做数据类型的校验,避免隐含的错误。含的错误。三、C+新的风格(4/5)使用函数原型和缺省参数n n函数原型函数原型 返回值类型返回值类型 函数名函数名( (参数列表参数列表); );n n缺省参数缺省参数 intint func(intfunc(int
3、 x,intx,int y=1,int z=2); y=1,int z=2);参数列表中的参数名称可以没有缺省参数必须全部在参数列表最后三、C+新的风格(5/5)新的内存分配函数mallocnewfreedeletenewnew不需要做类型转换。不需要做类型转换。intint *p=new int(5); *p=8; delete p; *p=new int(5); *p=8; delete p;intint *q=new int5; q2=5; *q=new int5; q2=5; delete q;delete q;四、内联函数内联函数的运行方式和有参数宏相同。内联函数有两种形式:n n有
4、有inlineinline的函数的函数n n在类定义中给出函数体的函数在类定义中给出函数体的函数五、引用(1/5)引用相当于给变量起个别名。引用相当于给变量起个别名。用用& &实现引用的定义:实现引用的定义: intint num = 10; num = 10; intint& ref = num;& ref = num; ref += 10; ref += 10; coutcoutnum;num;/ /输出输出2020 coutcoutref;ref;/ /输出输出2020五、引用(2/5)对对constconst变量变量/ /对不同数据类型变量的引用对不同数据类型变量的引用不共用内存。不共
5、用内存。 const const intint num = 10; num = 10; intint& ref = num;& ref = num; ref += 10; ref += 10; coutcoutnum;num;/ /输出输出1010 coutcoutref;ref;/ /输出输出2020五、引用(3/5)不能声明不能声明: :引用的引用引用的引用 int&pint&p; ;指向引用的指针指向引用的指针 intint&*p;&*p; 元素为引用的数组元素为引用的数组 intint& p3;& p3;可以声明指针的引用可以声明指针的引用 intint*&p;*&p;五、引用(4/5
6、)引用作为函数参数时,形参的变化将会影响引用作为函数参数时,形参的变化将会影响实参。实参。int swap(int& x,int&y) int t; t=x; x=y; y=t;int a=10,b=20;swap(a,b);couta“,”b;结果为:20,10五、引用(5/5)引用作为函数返回值,函数调用可以放在等引用作为函数返回值,函数调用可以放在等号左边。号左边。Int a=1,2,3,4,5;Int& index(int i) return ai;Index(2)=10;For (int i=0;i5;i+) coutai“,”;结果为:1,2,10,4,5,第二章 类和对象第二章
7、类和对象一、定义类(1/2) class 类名 访问权限: 数据成员; 函数成员; publicprivate(缺省值)protectedclass Location class Location private: private: intint x,yx,y; ; public: public: intint getXgetX() return x;() return x; intint getYgetY();(); void void init(intinit(int a,inta,int b) b) x= x=a;ya;y=b;=b; ;intint Location:getYLocat
8、ion:getY() ()return y;return y;一、定义类(2/2)不能对变量初始化类定义完成必须加;:为作用域运算符/类成员名限定符二、使用类和对象Location p1,*p2;Location p1,*p2;p1.init(1,2);p1.init(1,2);P2 = &p1;P2 = &p1;coutcoutp1.getX()p1.getX()endlendl; ;coutcoutgetYgetY()()endlendl; ;coutcoutp1.x;init(3,3);p2-init(3,3);五、this指针类的数据成员可以在类的函数成员中被访问。类的数据成员可以在类
9、的函数成员中被访问。Why?Why?不同对象的数据成员不互相影响。不同对象的数据成员不互相影响。Why?Why?不同对象调用函数成员时,不同对象调用函数成员时,thisthis指针指向不指针指向不同的对象。同的对象。return return x;x;returnreturn this-x; this-x;六、结构和联合关键词关键词classclass可以被换成可以被换成structstruct、unionunion来来定义类。定义类。structstruct: :成员的访问权限缺省为成员的访问权限缺省为publicpublic。union:union:成员的访问权限缺省为成员的访问权限缺省为
10、publicpublic,且,且某时刻只有一个成员出现。某时刻只有一个成员出现。n n联合不能做基类和派生类联合不能做基类和派生类n n联合中不能说明虚函数联合中不能说明虚函数n n无名联合不能有成员函数无名联合不能有成员函数七、类作用域(1/3)说明类时的一对说明类时的一对 形成类作用域。形成类作用域。成员函数内的标识符:成员函数内的标识符:局部变量局部变量= =类作用域类作用域= =全局变量全局变量class A class A intint i=10; i=10; intint i; i;intint A:getIA:getI() ()public:public: intint i=20
11、;return i; i=20;return i; intint getIgetI();();A a;A a; ;coutcouta.getIa.getI();();七、类作用域(2/3)类中定义的枚举成员,可以用类成员名类中定义的枚举成员,可以用类成员名限定存取,也可以用成员选择运算符存限定存取,也可以用成员选择运算符存取。取。类说明分定义性说明和引用性说明两类,类说明分定义性说明和引用性说明两类,在引用性说明阶段不能实例化对象,只在引用性说明阶段不能实例化对象,只能说明对象指针或引用。能说明对象指针或引用。七、类作用域(3/3)class A public:enum colorred,gr
12、een,blue;A a;/错A *p;A &q;void setValue(A a)p = &a;q=a;A obj1,obj2;coutobj1.redA:blue;obj1.setValue(obj2);八、空类/嵌套类空类:没有任何成员的类。空类:没有任何成员的类。嵌套类:在另一个类中声明的类。一般嵌套类:在另一个类中声明的类。一般嵌套类只用于它所声明的类中。嵌套类只用于它所声明的类中。class Aclass Apublic:public:class B class B intint I; I; ;B b;B b; ;九、类对象的性质及存取对象之间可以互相赋值。对象之间可以互相赋值。
13、对象可以用作数组元素。对象可以用作数组元素。可以说明指向对象的指针可以说明指向对象的指针对象可用作函数参数,为值调用对象可用作函数参数,为值调用一个对象可以做另一个对象的成员(对一个对象可以做另一个对象的成员(对象成员)象成员)第三章 构造函数与析构函数第三章 构造函数与析构函数一、构造函数(1/3)类中与类同名且没有返回值类型的成类中与类同名且没有返回值类型的成员函数员函数构造函数。构造函数。class A class A intint k; k;public:public:A();A();A(intA(int); ); ;可以有多个一、构造函数(2/3)声明对象new对象构造函数在实例化对
14、象时将被调用。A:A() A:A() coutcout“A()”“A()”endlendl; ;A:A(intA:A(int i) k= i) k=i;couti;cout“A(”i“)”“A(”i“)”endlendl; ; A a;A a;/ /输出输出A()A()A *c;A *c;A &d = a;A &d = a;c = new A(5);c = new A(5);/ /输出输出A(5)A(5)一、构造函数(3/3)缺省构造函数:无参数的构造函数。缺省什么都不做。复制初始化构造函数:参数类型为 类名& 的构造函数。缺省完成用参数对象复制出一个新的对象。A(A &p) k = p.k;
15、二、析构函数(1/2)类中名称为类中名称为 类名、没有返回值类型、没类名、没有返回值类型、没有参数的成员函数有参数的成员函数析构函数。析构函数。class A class A intint k; k;public:public:A();A();A(intA(int); );A();A(); ;只有一个二、析构函数(2/2)对象生命期结束delete对象析构函数在对象生命期结束时将被调用。A:A() A:A() coutcout“A()”“A()”1=类类2=X2=X / /析构函数调用顺序:析构函数调用顺序:X=X=类类2=2=类类1 1对象成员成员初始化列表七、其他数据成员所有数据成员的初始
16、化都所有数据成员的初始化都可以可以在成员在成员初始化列表中进行。初始化列表中进行。constconst成员、引用成员的初始化成员、引用成员的初始化必须必须通过成员初始化列表完成。通过成员初始化列表完成。参见参见p57.cppp57.cpp第四章 继承和派生类一、基本概念类的派生:通过特殊化已有的类建立新类的过程。基类(父类):已有的类。派生类(子类):新建立的类。继承表示类属关系,而不是构成关系。派生类直接拥有基类的所有成员派生类可以增加新成员派生类可以重新定义基类的成员函数派生类可以改变现有成员的属性二、继承的属性性质扩展性质约束构造函数和析构函数不被继承三、继承的分类单一继承多重继承输入设
17、备输出设备输入/输出设备人教 师学 生(单一继承)(多重继承)四、单一继承class 派生类名:访问控制 基类名;publicprivateprotected单一继承举例class Pointint x,y;public:void show();class Rect:public Pointint w,h;public:void show()Point:show();coutw“,”hendl;int area();五、保护成员兼有私有成员和公有成员双重角色。兼有私有成员和公有成员双重角色。基类的保护成员可以在派生类内部访问。基类的保护成员可以在派生类内部访问。保护成员举例class Poin
18、tprotected:int x,y;public:void show();class Rect:public Pointint w,h;public:void show()coutx“,”y “,”w“,”hendl;int area();六、公有派生基类公有成员派生类公有成员基类保护成员派生类保护成员基类私有/不可访问成员派生类不可访问成员公有派生赋值兼容规则派生类对象可以赋给派生类对象可以赋给基类对象基类对象派生类对象可以初始化基类引用派生类对象可以初始化基类引用派生类对象地址可以赋给派生类对象地址可以赋给基类指针基类指针Rect r;Rect r;p = r;p = r;Point p
19、;Point p;ptr = &r;ptr = &r;Point *ptr;Point *ptr;Point& pref = r;Point& pref = r; 注:注:ptr, ptr, prefpref只能访问只能访问PointPoint类的成员。类的成员。七、保护派生基类公有成员派生类保护成员基类保护成员派生类保护成员基类私有/不可访问成员派生类不可访问成员八、私有派生基类公有成员派生类私有成员基类保护成员派生类私有成员基类私有/不可访问成员派生类不可访问成员派生总结派生 权限基类成员权限publicprotected private类内 类外类内 类外 类内 类外publicprot
20、ectedprivate派生类内举例参见p70.cpp九、多重继承class class 派生类名:访问控制派生类名:访问控制 基类名基类名1 1, 访问控制访问控制 基类名基类名2 2 ; ;publicprivateprotected基类互不相同多重继承举例参见p71.cpp十、构造函数与析构函数调用顺序需要由派生类构造函数调用基类构造函数,完成基类成员的初始化。在成员初始化列表中实现。构造函数调用顺序:基类基类派生类对象成员派生类对象成员派生类派生类析构函数调用顺序:基类基类派生类对象成员派生类对象成员派生类派生类构造/析构函数调用举例参见p73.cpp参见p74.cpp十一、两义性及支
21、配规则两义性对一个名字的访问不确定。两义性检查先于访问权限,所以访问权限不能解决两义性问题。两义性举例class Apublic:int i;class Bpublic:int i;class C:public A,public Bpublic:void show()coutiendl;两义性及支配规则(续)类Y是类X的基类,则类X中的名字N支配类Y中同名字的N支配规则。被支配的名字在使用时必须做成员名限定(作用域分辨)。支配规则举例class Apublic:int i;class Bpublic:int i;class C:public A,public Bpublic:int i;voi
22、d show()coutiA:i B:i endl;支配规则举例参见p76.cpp参见p78.cpp十二、虚基类指定派生类的基类时,加关键字virtual将基类说明成虚基类。派生类可以有多个虚基类。虚基类使得多重继承路径中的公共基类只产生一个实例。虚基类举例class Apublic:int i;class B:virtual public A;class C:public virtual A;class D:public B, public C;D obj;obj.iobj.A:iobj.B:iobj.C:i虚基类说明虚基类指针/引用不能转换为派生类。派生类构造函数需要显式调用虚基类的构造函
23、数。虚基类举例参见p81.cpp第五章 多态性和虚函数一、基本概念多态性:又称为约束、动态约束,主要指函数调用的多态性。分类n n编译时的多态性:函数重载编译时的多态性:函数重载n n运行时的多态性:继承和虚函数运行时的多态性:继承和虚函数静态联编速度快动态联编速度慢class squaredclass squaredpublic:public:int squ(int k)return k*k;int squ(int k)return k*k;double squ(double k)double squ(double k)return k*k;return k*k; ;main()main()
24、 squared obj;squared obj;coutobj.squ(2)obj.squ(2.5)endl;coutobj.squ(2)obj.squ(2.5)endl; 二、静态联编三、动态联编参见参见p90.cppp90.cpp四、虚函数函数声明前加virtualclass Avirtual void func();void A:func()虚函数说明只能是类中的非静态成员函数只能是类中的非静态成员函数派生类中和基类完全相同的函数,如果派生类中和基类完全相同的函数,如果基类中是虚函数,派生类中的自动为虚基类中是虚函数,派生类中的自动为虚函数函数可以通过成员名限定强制使用静态联编可以通过
25、成员名限定强制使用静态联编派生类中定义的虚函数的访问权限不影派生类中定义的虚函数的访问权限不影响动态联编响动态联编构造构造/ /析构函数中调用虚函数采用静态析构函数中调用虚函数采用静态联编联编虚函数举例参见p92.cpp参见p93.cpp参见p95.cpp五、纯虚函数和抽象类纯虚函数:不需要提供函数的实现代码。class class 类名类名 virtual virtual 返回值类型返回值类型 函数名函数名( (参数列表参数列表) )=0=0; ; ;抽象类:包含纯虚函数的类。纯虚函数和抽象类说明一个类可以有多个纯虚函数。一个类可以有多个纯虚函数。抽象类至少有一个纯虚函数。抽象类至少有一个纯
26、虚函数。抽象类只能作为基类派生新类,不能实抽象类只能作为基类派生新类,不能实例化对象,但可以说明指向抽象类对象例化对象,但可以说明指向抽象类对象的指针。的指针。抽象类的派生类必须提供纯虚函数的实抽象类的派生类必须提供纯虚函数的实现代码,或者继续将它说明为纯虚函数。现代码,或者继续将它说明为纯虚函数。成员函数可以调用纯虚函数,但构造成员函数可以调用纯虚函数,但构造/ /析构函数中不行。析构函数中不行。纯虚函数和抽象类举例参见p97.cpp参见p98.cpp参见p100.cpp参见p101.cpp六、虚析构函数虚析构函数的调用采用动态联编。如果基类的析构函数为虚函数,则派生类的析构函数自动为虚函数
27、。虚析构函数举例参见p103.cpp参见p95.cpp第六章 进一步使用成员函数202.106.114.223/zk/6.1 静态成员静态变量静态对象静态成员一、静态变量只初始化一次只初始化一次main()main() for(int i=0;i3;i+)for(int i=0;i3;i+) static int n=0;static int n=0;n+;n+;coutnendl;coutnendl; 输出:123二、静态对象实例化对象时加static例如:假定A为一个类,static A a;则a为一个静态对象。静态对象举例参见pMy1.cpp三、静态成员class Astatic int
28、 x;public:static int getX();int A:getX() return x;静态成员说明静态成员为类所有对象共享不需要实例化对象,静态成员就存在,可用成员名限定直接访问静态成员函数没有this指针静态成员可以被继承,所有基类和派生类对象共享该成员静态成员的初始化不能在成员初始化列表中进行静态成员说明(续)为保证封装性,一般将静态数据成员定义为private,然后定义public的静态成员函数对其访问静态成员函数不能是虚函数静态数据成员只是一个引用性说明,必须在类定义外给出定义性说明静态成员举例参见pMy2.cpp6.2 const成员const变量const对象cons
29、t成员一、 const变量值不能被修改值不能被修改main()main() const int i=10;const int i=10;i=20;i=20;/ /错错int j = 30;int j = 30;const int* p1 = &i;const int* p1 = &i;*p1 = 30;*p1 = 30; / /错错int* const p2 = &i;int* const p2 = &i;p2 = &i;p2 = &i; / /错错 实例化对象时加const例如:假定A为一个类,const A a;则a为一个const对象。const对象的值不能被修改const对象只能访问c
30、onst成员函数二、const对象const对象举例class Apublic:int n;A(int k) n = k;int getN() return n;void main() const A a(10);a.n = 20; /错,a的值不能被修改couta.getN(); /错,a只能访问const成员函数const数据成员必须在成员初始化列表中被初始化const成员函数n n定义:定义:int fun() int fun() constconst; ;n n实现时实现时constconst也必须加也必须加n n成员函数中的成员函数中的thisthis指针及其所指向的内指针及其所指向
31、的内容都是容都是constconst的,即不能在的,即不能在constconst成员函成员函数中修改数据成员的值数中修改数据成员的值n n构造构造/ /析构函数不能加析构函数不能加constconst三、const成员const 类名* const this;const成员举例参见pMy3.cpp6.3 友元类的友元可以访问类中的所有成员友元破坏了封装,但提高了程序效率友元函数友元类一、友元函数在类中声明,声明前加friendclass Pointint x,y;friend void show(Point&);void show(Point& p)coutp.x“,”p.y只能用类运算符类运
32、算符和友元运算符举例参见p130.cpp参见pMy9.cpp参见pMy10.cpp7.3 +、-运算符的重载类运算符objobj.operator()objobj.operator(0)obj0友元运算符objoperator(obj)objoperator(obj,0)obj0+、-运算符的重载举例参见p133.cpp参见p134.cpp7.4 流类库流类:执行输入输出操作的类体系流类库:提供流类实现的系统库一、流类库的类等级iosistreamostreamiostreamstreambuf二、流类库预定义的四个流cin:标准输入设备cout:标准输出设备cerr:标准错误输出设备(非缓冲
33、方式)clog:标准错误输出设备(缓冲方式)7.5 运算符的重载ostream& operator(istream& s,类)return s;运算符的重载举例参见p137.cpp7.6 格式控制iso类提供的接口内部格式控制函数一、iso类提供的接口iostream.h中定义的iso类实现iso类通过设置格式标志实现格式控制格式标志存放在iso类的长整型成员中,每个标志占一位二、内部格式控制函数iomanip.h中定义可以通过设置格式标志实现格式控制,也可以直接设置控制格式可以把格式控制嵌入到输入输出中间三、格式控制比较isoiso类提供的接口类提供的接口( (cout.)cout.)内部格
34、式控制函数内部格式控制函数( (cout)cout)数据宽度数据宽度 width(10)width(10)setw(10)setw(10)数据精度数据精度 precision(2)precision(2)setprecision(2)setprecision(2)填充字符填充字符 fill(0)fill(0)setfill(0)setfill(0)设标志位设标志位 setf(ios:left)setf(ios:left)setiosflags(setiosflags(iosios:left):left)清标志位清标志位 unsetf(ios:left)unsetf(ios:left)reset
35、iosflags(ios:leresetiosflags(ios:left)ft)不同进制不同进制 setf(ios:dec)setf(ios:dec)decdec格式控制举例参见p139.cpp参见p140.cpp7.7 文件操作方式fstream.h中定义了三种文件流:输入文件流输出文件流输入/输出文件流一、文件I/O流类库的类等级iosistreamostreamiostreamstreambuffstreambaseifstreamofstreamfstreamfilebuf二、文件操作步骤打开文件流fstream f1;f1.open(文件名,文件打开方式,文件保护方式= fileb
36、uf:openprot);ios:inios:outios:appios:ateios:nocreatefilebuf:sh_nonefilebuf:sh_readfilebuf:sh_write文件操作步骤(续)对文件流操作get/put(char ch) getline(char* ch,int count,char delin=n)read/write(char* ch,int count)关闭文件流f1.close();文件操作举例参见p142.cpp7.8流的错误处理发生I/O错误后,错误性质记录在ios类的数据成员中,将相关标志位置位。ios类提供成员函数用于检查流对象的当前状态i
37、os类提供成员函数用于清除/设置流的状态位rdstate()eof(),good()Fail(),bad()clear(int 标志位=0)第八章 模板8.1 模板的概念问题:提供逻辑功能完全相同的函数,只是操作数据类型不同。eg) eg) 求两个数据中较大的一个求两个数据中较大的一个创建一些类,除了数据成员类型不同,其它的功能都相同。eg) eg) 数组类数组类函数模板类模板8.2 函数模板templateT max(T x, T y)return (xy)?x:y;函数模板说明类型参数可以有多个,每个都需要写class,作用域为该模板范围函数模板不做参数类型转换函数调用时,由函数模板生成相
38、应的模板函数通过显示声明非模板函数来阻止编译器生成模板函数函数模板说明(续)类型参数必须被用于函数模板的形参函数模板声明必须在函数调用之前被编译器知道函数模板举例参见pMy11.cpp8.3 类模板template class A T x,y;public:A(T a,T b) x = a;y = b;T getXY();类模板(续)templateT A:getXY() return x+y; 实例化对象:A obj(1,2);coutobj.getXY();类模板举例参见pMy12.cpp8.4 模板与继承的关系模板模板继承继承处理数据处理数据/ /方式方式不同类型数据的不同类型数据的相同操作相同操作任意数据,任任意数据,任意操作意操作类成员类成员不稳定不稳定较稳定较稳定动态性动态性动态动态静态静态类间关系类间关系无无有有