已阅读5页,还剩13页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
选择题10分 阅读程序题18分 完成程序题30分填空编程题12分 阅读分析题 10分编程题 20分一、 C+前期准备变量的引用,int x,&px=x; 那么引用变量px是x的别名,它们是同一内存空间。如果想通过函数的调用改变一个变量值,就可以通过引用来实现。在上学期的C语言学习中是通过指针来实现这一功能的。/例1 变量的引用#includeusing namespace std;void f(int x,int &y,int *p)x=x+10;y=x+10;*p=x+10;main()int a=1,b=2,c=3;f(a,b,&c);couta b cendl;运行结果如下:1 21 21Press any key to continue从结果可以看出,主函数中定义的变量a不会改变,变量b和c发生了改变,那是因为,变量b作为实参传递给了函数f中的引用变量y,当引用变量的值改变了,主函数中的变量b也就改变了。变量c的地址作为实参传递了函数中的指针变量p,当p中所指的内容改变了,变量c也改变了。一、 类的定义类的定义与结构体不同的地方就是将数据(数据成员)和对数据的操作(成员函数)放在一起,作为不可分割的整体。而结构体中只有数据。类就是用户自定义的数据类型,类是抽象的,不会为类分配存储空间,而对象是具体的,会为对象分配存储空间。类中除了有数据成员外还有成员函数,成员函数可以访问类中的私有成员。如果不说明,所有的成员都是私有的。/例2 类的定义#includeusing namespace std;class Myclass /class后跟类名,一般以大写字母开头,类包含两个成员private: /私有的,也可以缺省,即默认的为私有的int i; /私有数据成员protected: /保护的int m; /保护数据成员public: /公共的int p; /公共的数据成员void set(int x1,int x2,int x3)/公共成员函数,一般情况下,成员函数都是公共的i=x1;m=x2;p=x3;/一定要有一个对类中的数据成员初始化的成员函数,这样才有意义;int main()Myclass my; /定义对象my,会为其分配内存空间my.set(1,2,3); /给对象赋初值return 0;成员函数可以重载、可以设置参数的默认值、可以定义为内联成员函数、静态成员函数(static)、常成员函数。1、内联函数的使用如果满足内联函数的条件,尽量使用内联函数。定义为内联函数后,每当在类外部调用该函数时,定义的函数代码会在调用函数位置展开,而不是产生一个拷贝。只要满足内联函数条件,一般在类内部定义的成员函数是内联函数,即使不说明为inline。如果在类外定义内联函数一定要说明为inline。2、 常成员函数当类的成员函数无需改变数据成员时,可以把该成员函数定义为常成员函数。常成员函数不能更新对象的数据成员,只能使用类中的数据成员。如果例2中的再增加二个成员函数geti()与getm(),因为无需改变数据成员的值,所以可以定义为常成员函数,定义格式如下:int getm( ) const /注意定义格式。 return m; int geti() const return i; 如果一个对象被定义为常对象,就不能被更新了,所以只能调用常成员函数。一般对象当然也能调用常成员函数。常对象的定义格式如下:格式:类名 const 对象名 或 const 类名 对象名常对象中的数据成员为常变量且必须要有初值,常对象在定义时必须进行初始化,而且不能被更新。例3 完成程序题1在下面给出的时间类Time中,增加show函数,以“时:分:秒”的格式显示时间值,要注意保证程序能够通过编译且正确运行。#include using namespace std;class Timepublic: Time(int h,int m,int s):hour(h),minute(m),sec(s)void showtime() const /一定要是常成员函数,因为主函数中定义的对象是常对象 couthour:minute:secendl; private: int hour,minute,sec; int main() const Time wakeTime(7,0,0); /是常对象wakeTime.showtime();return 0;3、 静态成员当成员不属于某一个对象,而是属于整个类时,要定义为静态成员,包括静态数据成员和静态成员函数。用static来声明。静态数据成员必须对它进行初始化。初始化时要在类外,不用再加static了;定义时一定要带上类名: 。 静态成员函数是专门用来对静态数据成员操作的。例4 对于下面给出的Myclass类,在类外增加语句给count赋初值,增加静态成员函数fun,使得运行结果为:3 2 1 #includeusing namespace std;class Myclasspublic: Myclass()+count; del()-count;static int fun()return count; /一定要是静态成员函数private: static int count;int Myclass:count=1; /在类外赋值,一定要加上类名int main() Myclass m1,m2,m3; m1.del();coutMyclass:fun() ; m2.del(); coutMyclass:fun() ; m3.del();coutMyclass:fun() ; return 0;二、 构造函数、析构函数、复制构造函数、友元函数1、构造函数学习了构造函数以后,对数据成员的初始化工作是由构造函数来完成的。例2如果用构造函数来实现的话,程序如下。例5 构造函数#includeusing namespace std;class Myclassprivate:int i;protected:int m;public:int p;Myclass(int x1,int x2,int x3) /构造函数i=x1;m=x2;p=x3; ;int main()Myclass my(1,2,3); /注意定义对象的改变return 0;说明:构造函数名与类名同名;没有任何返回类型,即使是void也没有;构造函数可以重载;定义对象要按构造函数的定义形式给实际参数,例2中定义对象时没有给参数,那是因为有一个默认的构造函数是无参的。如果不定义构造函数,系统会在定义对象时自动调用默认的构造函数。当定义了构造函数以后,默认的构造函数就不存在了,所以在例5中不能像在例2中定义对象,一定要给出实际参数。定义对象时,会自动调用构造函数。例6 编程题编写一个类Calculate,计算出sum=1+2+3+n值。类中包含数据成员n,成员函数包括初始化n的构造函数,求sum值的sumf函数,输出n各求和值的show函数。写出主函数,输入n的值,并输出求和结果。#includeusing namespace std;class Calculateint n;public:Calculate(int nn=0):n(nn)int sumf()int i,s=0;for(i=1;i=n;i+)s+=i;return s;void show()coutn=n 1+2+3+.+n的值是:sumf()endl; ;main()Calculate c(10);c.show(); 运行结果如下:n=10 1+2+3+.+10的值是:55Press any key to continue2、析构函数析构函数是类中特殊的成员函数,当对象撤消时,就会马上被调用,其作用是善后处理。它没有返回类型,没有参数,不能随意调用,也不能重载。只是在类对象生命期结束的时候,由系统自动调用。构造函数不同于析构函数,可以有参数,可以重载。例7 如果例4中把成员函数del用析构函数来实现,程序如下,请给出运行结果。#includeusing namespace std;class Myclasspublic: Myclass()+count; Myclass()cout-count ; static int fun()return count;private: static int count;int Myclass:count=1;int main() Myclass m1,m2,m3;coutMyclass:fun() ; return 0;运行结果:4 3 2 1 Press any key to continue 为了说明问题,在析构函数中用了输出语句,但实际情况下是析构函数是用来释发资源而用的。 当有多个对象时,自动执行的顺序一定要清楚,先构造的后析构,后构造的先析构。例8 阅读程序#includeusing namespace std;class Studentpublic: Student(int n):num(n) coutconstructor call numendl; Student() coutconstructor call numendl; private: int num; ;int main() Student stud3=1,2,3; return 0;运行结果:constructor call 1constructor call 2constructor call 3constructor call 3constructor call 2constructor call 1Press any key to continue3、 复制构造函数复制构造函数在以下3种情况下会被调用:1) 用类的一个已知的对象去初始化该类的另一个正在创建的对象。2) 采用传值调用方式时,对象作为函数实参传递给函数形参。3) 对象作为函返回值。当类的定义有动态资源分配时,对象的复制才需要自己编写复制构造函数。复制构造函数的形式如下:Myclass:Myclass ( Myclass & x) /分配动态资源;/各对应数据成员赋值;例9 阅读程序,下面这个程序实际不必自己编写复制构造函数,但为了说明问题定义了一个复制构造函数。#include using namespace std;class MyClasspublic:MyClass(int X=0):x(X) cout构造函数 x=xendl; MyClass(MyClass& m) x=m.x; cout复制构造函数 x=xendl;private:int x;int main() MyClass m1(1),m2,m3(m1),m4=m1; return 0; 运行结果构造函数 x=1构造函数 x=0复制构造函数 x=1复制构造函数 x=1Press any key to continue4、 友元函数我们知道类的一大特性就是封装性,在类外是不能访问私有成员的,而有时为了增加效率而不惜破坏封装性,通过友元来对有好友关系的类中的私有成员进行访问。友元可以是普通函数,也可以另一类的成员函数,还可以是一个类。我们只要了解是普通函数的情况。例10 定义一个Point类,其中有数据成员x,y。构造函数用于数据成员的初始化,用友员函数来求二点的距离。#include #include using namespace std;class Pointpublic: Point(int X,int Y) x=X;y=Y;friend float Distance(Point p1,Point p2); /声明成友元函数private: int x,y;float Distance(Point p1,Point p2) return sqrt(p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y);/这是普通函数,要想访问类point中的私有成员,一定要说明成类Point的友员int main() Point p1(1,1),p2(2,2); coutDistance(p1,p2); return 0; 三、 类模板例11 类模板的定义#include#includeusing namespace std;template /声明模板 格式: template class TAnyTemp /模板类 T x,y;public:TAnyTemp(T X,T Y)x=X;y=Y;T add()return x+y;int main()int ia=1,ib=2;double da=3.1,db=4.2;string sa=abc,sb=def;TAnyTempi(ia,ib); /调用时的格式:类模板名对象名(实参表列)couti.add()endl;TAnyTempd(da,db); coutd.add()endl;TAnyTemps(sa,sb);couts.add()endl;四、 运算符重载重载运算符的规则如下:不是所有的运算符都可以通过重载而被赋予新的含义的。能够被重载的操作还需遵守以下规则。1)C+不允许用户自己创建新的运算符,只能对已有的C+运算符进行重载。2)操作个数不变、优先级不变、结合性不变3)不能有默认的参数4)重载运算符必须和用户定义的类对象一起使用,其参数至少应有一个是类对象或类对象的引用。也就是说参数不能全是C+的标准类型,以防用户改变了原标准类型的运算性质。5)重载后的操作符的新意思要与原意一致。6)基本规则 a)一元操作符可以是不带参数的成员函数或带一个参数的非成员函数。b)二元操作符可以是带一个参数的成员函数或带两个参数的非成员函数。c)operator不能定义为成员函数。d)重载 operator+ 和 operator- 时带一个 int 参数表示后缀,不带参数表示前缀。例12 定义一个点Point,实现+的操作,即x、y坐标值分别加1;重载提取运算符实现Point类对象的输入运算;重载流插入运算符以“(x,y)”格式输出Point类对象数据成员的值。#include class Pointpublic: Point(int X=0,int Y=0) x=X,y=Y; friend ostream& operator(istream& input,Point &p); Point &operator+() x+;y+; return Point(x,y);private: int x,y;ostream& operator(ostream& output,Point p) return output(p.x,p.y)(istream& input,Point& p) /必须是引用 cout请输入二点的值:p.xp.y; int main() Point p; cinp; coutp;p+;coutp; return 0; 六、 类的继承与派生1、单继承面向对象程序设计的三大特性是封装性、继承性、多态性。以上所讨论的问题都是有关类的封装性出发来考虑的,下面讨论类的继承性。例13 编程题,先定义一个基类Point,再由基类派生一个圆Circle类。#includeusing namespace std;class Pointprotected:int x,y;public:Point(int a,int b)cout点的构造函数调用endl; x=a;y=b; ;class Circle:public Pointint radius;public:Circle(int a,int b,int r):Point(a,b) /要负责基类的构造cout圆的构造函数调用endl; radius=r;float area()return 3.14159*radius*radius;void display() /在派生类中可以使用基类中的保护成员x,ycout点:(x,y) 半径:radius 面积:area()endl;int main()Circle c(1,2,3);c.display(); return 0; 知道构造函数和析构函数的执行顺序吗?先构造的后析构,后构造的先析构,下面来看个典型的程序。例14 阅读程序#include using namespace std;class Apublic: A() cout构造函数 An; A() cout析构函数 An; ;class B:public Apublic: B() cout构造函数 Bn; B() cout析构函数 Bn; ;class C:public Bpublic: C() cout构造函数 Cn; C() cout析构函数 Cn; ;int main() C c; return 0;结果如下:构造函数 A构造函数 B构造函数 C析构函数 C析构函数 B析构函数 APress any key to continue当定义圆时,也可以用组合的方式,也就是说点是其中的一个数据成员中类Point,也就是子对象,有子对象的类是怎样的?例15 阅读程序#includeusing namespace std;class Pointprotected:int x,y;public:Point(int a,int b)x=a;y=b;cout点的构造函数endl;class CirclePoint p;int radius;public:Circle(int a,int b,int r):p(a,b),radius(r) /要负责子对象的构造cout圆的构造函数endl; float area()return 3.14159*radius*radius; /注意,在这里没定义display,是因为不能使用Point中的私有成员x,y。;int main()Circle c(1,2,3); return 0; 运行结果如下:点的构造函数圆的构造函数Press any key to continue派生类可以由基类公共派生、保护派生、私有派生。一般情况下使用公共派生。派生类可以使用基类的哪些成员,是由基类中的定义以及以什么方式派生来确定的。下面来看一个程序,我们来看各成员在各类中的访问情况。例16 阅读程序,分析各成员在各类中的访问情况。 class Aint i;public:void f1();protected:void f2();class B:public Aint m;public:void f3();int k;class C:protected Bint n;public:void f4();protected:int m;class D:private Cint q;public:void f5();protected:int p;类if1f2B:mf3knf4C:mqf5pA私有公有保护B公公有保护私有公共公共C保保护保护保护保护私有公共保护D私私有私有私有私有私有私有私有公共保护2、多重继承前面讨论的是单继承,即一个类是从一个基类派生而来的。这里讲多重继承,即一个派生类同时继承多个基类。下面从一个最简单的多重继承的实例中来看怎么声明多重派生。例17 阅读程序#includeusing namespace std;class Aint a;public:A()coutAendl;A()coutAendl;class Bint a;public:B()coutBendl;B()coutBendl;class Cint a;public:C()coutCendl;C()coutCendl;class D:public A,public B,public C public:D()coutDendl;int main()D d;return 0;运行结果:ABCDCBAPress any key to continue从运行结果可以看出,调用基类构造函数的顺序是按照声明派生类时基类出现的顺序。多重继承会引起二义性,有一个有效的解决方案是增加一个虚基类。使得在继承间接共同基类时只保留一份成员。这样就不会产生二义性了。例18 阅读程序#include using namespace std;class Apublic: A() coutAendl;class B:virtual public Apublic: B() coutBendl;class C:virtual public Apublic: C() coutCendl;class D:public B,public Cpublic: D() coutDendl; ;int main() D d; return 0;运行结果:A B C D如果程序中没有virtual,那么基类A会被构造二次。其结果会是: A B A C D以上程序中类的构造函数是无参的,所以看不到派生类的构造函数是怎样编写的,看下面的例子可以知道怎样去编写派生类的构造函数。例19 阅读程序#includeusing namespace std;class N int a;public:N(int i)cout构造函数Nendl;a=i; ;class A:virtual public Npublic:A(int i):N(i)cout构造函数Aendl; /负责直接基类的构造;class B:virtual public Npublic: B(int i):N(i)cout构造函数Bendl; /负责直接基类的构造;class C:public A,public Bpublic: C(int i):N(i),A(i),B(i)cout构造函数Cendl; /除负责直接基类的构造,还要构造虚基类;int main()C c1(10); 运行结果如下:构造函数N构造函数A构造函数B构造函数CPress any key to continue如果不是虚拟继承,程序改写如下:例20 阅读程序#includeusing namespace std;class N int a;public:N(int i)cout构造函数Nendl;a=i; ;class A: public N /没有虚拟继承public:A(int i):N(i)cout构造函数Aendl; /负责直接基类的构造;class B: public N /没有虚拟继承public: B(int i):N(i)cout构造函数Bendl; /负责直接基类的构造;class C:public A,public Bpublic: C(int i):A(i),B(i)cout构造函数Cendl; /在这里不需要去构造N;int main()C c1(10); 运行结果如下:构造函数N构造函数A构造函数N构造函数B构造函数CPress any key to continue七、多态性多态性分为静态多态和动态多态,静态多态性是由重载实现的,而动态多态性是由虚函数实现的。在成员函数声明的前面加上virtual修饰,即该函数声明为虚函数。下面来看一个实例/例21 #includeusing namespace std;class Pointprotected:int x,y;public:Point(int a,int b)x=a;y=b;void show() cout(x,y)endl;class Rectangle:public Pointint length,width;public:Rectangle(int a,int b,int l,int w):Point(a,b) /要负责基类的构造length=l;width=w;void show() cout(x,y) l=length w=widthendl; ;int main()Point p(1,2);p.show();Rectangle r(1,2,3,4);r.show();运行结果:(1,2)(1,2) l=3 w=4Press any key to continue因为派生类即基类,所以派生类的对象可以赋值给基类的对象、派生类的对象可以初始化基类的引用、派生类的对象的地址可以赋值给指向基类的指针,派生类可以作为实际参数传给基类的形参。从而出现了多态性的问题。#includeusing namespace std;class Pointprotected:int x,y;public:Point(int a,int b)x=a;y=b;void show() cout(x,y)endl;class Rectangle:public Pointint length,width;public:Rectangle(int a,int b,int l,int w):Point(a,b) /要负责基类的构造length=l;width=w;void show() cout(x,y) l=length w=widthshow();fun(r); /派生类对象可以作为实际参数传给基类的形参运行结果: (1,2)(1,2)(1,2)(1,2)Press any key to continue输出的结果
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 早餐美食课件
- 2025版屋顶光伏板防水保护工程合同
- 2025版房地产售后回租包销服务协议
- 早道日语课件
- 2025版房地产合作开发项目税务筹划协议
- 二零二五年度地质灾害勘查合同范本范本
- 2025版能源企业退休技术专家聘用合同范本
- 二零二五年度桥梁检测与养护综合服务合同
- 二零二五年防火涂料施工项目设计与施工总承包合同
- 2025版学校教室装修施工合同页5
- 内镜中心人员培训管理制度
- 体育赛事消防应急预案制定
- 中国高血压防治指南(2024年修订版)要点解读
- 2024-2030年中国自动驾驶重卡行业发展状况与前景预测报告
- 剧毒化学品从业单位备案登记表
- 2024年企业人力资源管理师三级考试大纲
- DL∕T 1396-2014 水电建设项目文件收集与档案整 理规范
- DB15-T 3516-2024 野生动物救护站建设规范
- 电费代缴委托书
- 上海市嘉定区2023-2024学年三年级下学期期末数学试卷
- 眼科常见病例与分析总结
评论
0/150
提交评论