




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Chap3 C+ 的类李春花QQ: 471767100武汉光电国家实验室B405类和对象对象(object)表示现实世界中可以明确识别的实体。例如,学生、圆、按钮等。对象具有状态和行为。类(class)定义了同一类对象共有的属性和方法。类是对象的模板、蓝图。对象是类的实例。状态(变量)行为(方法)姓名:张三学号:0001身高:1.73学习工作娱乐class Circle private: double radius ; public: Circle() ; Circle(double r); double findArea() ;;#include “Circle.h”Circle:Circl
2、e() radius = 1.0;Circle:Circle(double r) radius = r;double Circle:findArea() return radius * radius * 3.14;示例-圆类数据成员函数成员声明构造函数声明Circle c1;radius=1.0;Circle c2(3.0);radius=3.0;Circle c3(15.0);radius=15.0;构造函数定义函数成员定义Circle.hCircle.cppmain.cpp#include “Circle.h”void main() Circle c1, c2(3.0); coutc1.f
3、indArea(); cout 0.0 ) radius = r; else radius = 1.0; Circle c1; /用户没指定参数,调用缺省构造函数 Circle c2( 5.0 ); /调用带参数构造函数,实参5.0传给形参r,将对象c2的 / 半径设为5.0 cout c1.radiuse; /1.0 cout c2.radiuse; /5.0类的声明及定义类的声明:由保留字class、struct或union加上类的名称构成。类的定义:包括类名的声明部分和类由 括起来的主体两部分构成。类的实现:通常指类的函数成员的实现,即定义类的函数成员。class 类型名; /前向声明c
4、lass 类型名 /类的定义private: 私有成员声明或定义; protected: 保护成员声明或定义; public: 公有成员声明或定义; ; 类保留字:class、struct或union可用来声明和定义类。访问权限封装机制定义数据成员、函数成员和类型成员的访问权限, 提供对外访问接口访问内部私有或保护数据。包括三类:private:私有成员可被本类的函数成员访问,不能被派生类函数成员、其它类的函数成员和普通函数访问。protected:受保护成员可被本类和派生类的函数成员访问,不能被其它类函数成员和普通函数访问。public:公有成员可被任何函数成员和普通函数访问。注意:类的友元
5、不是当前类的成员,可以在private、protected和public等任意位置说明,友元可以像类自己的函数成员一样访问类的所有成员。进入class定义的类时,缺省访问权限为private;进入struct和union定义的类时,缺省访问权限为public。7class FEMALE /缺省访问权限为privateint age; /私有的, 本类函数成员和友员可访问public:/访问权限改为publictypedef char *NAME; /公有的, 都能访问protected: /访问权限改为protectedNAME nickname; /本类和派生类函数成员、友员可访问NAME
6、getnickname ( ) return nickname; ; /自动内联public:/访问权限改为publicNAME name; /公有的, 都能访问 w; void main (void) FEMALE :NAME n=; /任何函数都能访问公有name n=w.nickname; /错误,main不得访问保护成员 n=w.getnickname ( ) ; /错误, main不得调用保护成员 int d=w.age; /错误, main不得访问私有age【例3-4】定义FEMALE类 访问权限用法使用private、protected和public保留字标识每一区间
7、的访问权限,同一保留字可以多次出现; 同一区间内可以有数据成员、函数成员和类型成员,习惯上按类型成员、数据成员和函数成员分开; 成员可以任意顺序出现在类定义中,函数成员的实现既可放在类体外面;也可内嵌在类体定义中,此时会自动成为内联函数; 若函数成员在类的定义体外实现,则须在函数返回类型和函数名之间,使用类名和作用域运算符“:”指明该函数成员所属的类; 声明类时不允许初始化数据成员,应由构造函数完成; 类的定义体花括号后要有“;”作为类体结束标志。9class COMP double r, v; public:COMP (double rp, double vp) r=rp; v=vp; /自
8、动内联inline double getr ( ); /inline保留字可以省略, 后面有定义double getv ( ) ; ; inline double COMP:getv ( ) return v; /定义内联void main (void) COMP c(3, 4) ; double r=c.getr ( ) ; /此时getr的函数体未定义, 内联失败double v=c.getv ( ) ; /函数定义在调用之前, 内联成功inline double COMP:getr ( ) return r; /定义内联【例3-7】定义一个复数类 内联函数必须在使用前进行定义10#inc
9、lude #include #include struct STRING char *s; STRING (char *) ; STRING ( ) ; ; STRING:STRING (char *t) s= (char *) malloc (strlen (t) +1); strcpy (s, t) ; coutConstruct: s; STRING:STRING ( ) /防止反复释放内存 if (s=0) return; coutDeconstruct: s; free (s) ; s=0; /提倡0代替null指针void main (void) STRING s1 (String
10、 1n) ; STRING s2 (String 2n) ; STRING (“Constantn”); /常量对象 cout RETURNn; /自动析够构s2, s1Construct: String 1Construct: String 2Construct: ConstantDeconstruct: ConstantRETURNDeconstruct: String2Deconstruct: String1构造析构顺序3.4new和delete内存管理函数和new、delete的区别:内存分配:malloc为函数,实参用值表达式,分配后内存初始化为0;new为运算符,操作数用类型表达式
11、,先在底层调用malloc,然后调用构造函数; 内存释放:free为函数,实参用指针类型值表达式,直接释放内存;delete为运算符,操作数为指针类型值表达式,先调用析构函数,然后底层调用free。如为简单类型 (没有构造、析构函数) 指针分配和释放内存,则new和malloc、delete和free没有区别,可混合使用,如new分配的内存可用free释放。12new 类型表达式:int *p=new int; /等价int *p=new int (0) ; 数组形式仅第一维下标可为任意表达式,其它维为常量表达式:int (*q) 68=new intx+2068; 【例3-13】为对象数组分
12、配内存时,必须调用参数表无参构造函数。delete 指针指向非数组的单个实体使用delete p, 如p指向对象,则先调用析构函数,再释放对象所占的内存。delete 指针指向任意维的数组时使用delete p; 否则内存泄露如p指向对象数组,则对所有对象 (元素) 先调用析构函数。然后释放对象数组占有的内存。13#include #include class ARRAY /class体的缺省访问权限为privateint*a, r, c; public: /访问权限改为publicARRAY (int x, int y) / int型可用malloc r=x ; c=y ; a=new in
13、t r *c ; ARRAY ( ) if (a) delete a; a=0; /可用free(a); 也可用delete a; void main (void) ARRAY y (3, 5) , *p; p=new ARRAY(5, 7); delete p; /main返回前析构y/不能用malloc, ARRAY需要调构造函数/不能用free, 否则p未调用析构函数14两种内存管理方式的区别ar=0c=0r. c =35个整型元素p(a) p = new Array(5,7)Step 1: 为对象分配内存p=(Array *)malloc(sizeof(Array)Step 2: 调用
14、构造函数a=new int r * c(b) p = (Array *)malloc(sizeof(ARRAY)a=nullr=0c=0pr=5c=715ar=5c=7r.C =35个整型元素p(d) delete pStep 2: 释放Array对象内存free(p)Step 1: 先调析构函数delete a,释放a指向的内存(b) free(p)ar=5c=7r.C =35个整型元素p直接释放Array对象内存,没有调析构函数,导致a指向的35个整型元素所占内存没释放两种内存管理方式的区别16new还可对已经析构的变量重新构造,从而减少变量的说明个数,提高内存的使用效率。(需高版本C+编
15、译器支持,通常要包含iostream.h) STRING x (Hello!) , *p=&x; x. STRING ( ) ; /析构对象,但对象所占内存没释放new (&x) STRING (The World) ; new (p) STRING (The World) ; 这种用法可以节省内存或栈的空间。173.5隐含参数thisthis指针是一个隐含的const指针,不能移动或对该指针赋值(即该指针是const的)。它是普通函数成员的第一个参数,指向要调用该函数成员的对象。*this代表当前被指向的对象。当通过对象调用函数成员时,对象的地址作为函数的第一个实参首先压栈,通过这种方式将对
16、象地址传递给隐含参数this。构造函数和析构函数的this参数类型固定。由于析构函数的参数表必须为空,this参数又无类型变化,故析构函数不能重载。类的静态函数成员没有隐含的this指针。18this指针class A int age;public: void setAge( int age) this-age = age;/this类型:A*const this A a; a.setAge(30); /函数setAge通过对象a被调用时,setAge函数的第一个参数是 / A*const this指针,指向调用对象a。 / this-age = a.age = 30a的地址传给this19c
17、lass TREE int value; /保存节点值 TREE *left, *right; public: TREE(int) ; /TREE * const this TREE( ) ; /TREE * const this const TREE *find (int) const; / 这个const是修饰this指针,/const TREE * const this; TREE:TREE (int value) /隐含参数this指向要构造的对象this-value=value; /等价于TREE:value=valueleft=right=0; /C+提倡空指针NULL用0表示co
18、nst TREE* TREE:find (int v)const /this指向调用对象if (v=value) return this; /this指向找到的节点 if (vfind (v) : 0; /递归查左子树return right!=0?right-find (v) :0; /递归查右子树 /查右子树, 调用时新this=right3.6对象初始化若存在以下因素, 必须自定义构造函数:类若定义了只读或引用类型的非静态(static)数据成员, 这些成员必须通过自定义构造函数初始化; 若类A包含类B的非静态对象成员,而类B的构造函数参数表都有参数,则类A必须自定义构造函数(无论参数表
19、是否有参数):以便用实参初试化类B的非静态对象成员。注意:C+缺省的无参的A( ) 只会调用无参的B( ) 。若子类的基类只定义了参数表有参数的构造函数,这些基类成员必须通过带参数的构造函数初始化; 那么子类必须自定义构造函数(无论参数表是否有参数) ,否则无法传递参数给父类构造函数初始化位置:在构造函数的参数表之后、函数体之前, 所有的基类和数据成员都应在此初始化(称为成员初始化列表), 并且只能在该处初始化一次,在其函数体内的赋值不应视作初始化。21数据成员初始化方法:数据成员不能在定义时初始化,必须用构造函数初始化; class A int i= 0; /错,不能在定义时初始化 。 ;成
20、员按照在类体内定义的先后次序初始化,与出现在初始化列表的次序无关; class A int i; int j; public: A( ):j(0),i(0) /还是先初始化 i, 后初始化 j。按定义顺序初始化 i = 1; j = 1; /在函数体内不应看做初始化,而是赋值 ;22数据成员初始化方法:普通数据成员没有出现在初始化列表位置时,若所属对象为全局、静态或new的对象,将具有缺省值0; class A int i; public: A( ) ; A a; /a为全局对象, a.i = 023数据成员初始化方法:只读、引用、对象成员只能出现在初始化列表中; 【例3-16】 struct
21、 B int i; B(int x):i(x) /B只定义了带参数构造函数 ; class A /以下三种情况之一,必须自定义构造函数 const int i; /只读 int j; int &ri; /引用 B b; /对象成员, /B只有带参数的构造函数 public: A( ):i(0) , j(0), ri (j) , b(1) j=3; ;从这个例子可以看出:由于类 B只定义了带参数的构造函数,为了初始化对象成员b,A必须自定义构造函数。否则没有机会传递参数给B的构造函数。同样的道理,如果A有基类,而且基类只定义了带参数的构造函数,我们必须定义A的构造函数。24数据成员初始化方法:基
22、类和非静态对象成员没有出现在初始化列表位置时,此时必然调用其无参构造函数对其初始化( 因为无法传递参数); 如果类仅包含公有成员且没有定义构造函数,则可以采用同C兼容的初始化方式,即:使用花括号初始化数据成员; 用new分配的对象数组必须调用无参构造函数初始化。25struct A int a, b; w=1, 2; /全部为公有成员, 未定义构造函数class B int c; public: B (int x) c=x; ; /c可以不出现在初始化列表里 /最好是B (int x) :c (x) class C const int d; /只读 B e; /e为对象成员,类B构造函数参数表
23、有参数, 类C须定义构造函数public: C ( ) :d (0), e (0) ; /无参构造函数 C (int x) :e (x), d (x) ; /重载构造函数按定义顺序d、e初始化 C (int x, int y) :d (x) , e (y) ; /只读、引用、对象成员如d、e不能在 中赋值; void main (void) B b1 (8), b2=9, b3= (2, 3) ; C c16=3, (4, 5), C (6), C (7, 8), C ( ) ; C *qc=new C(3) , *rc=new C4; /对象数组为其元素调用C ( ) 共4次 delete
24、qc; delete rc; /对象数组用delete 析构4次、释放1次对象数组/等号右边只能一个值, 等于B b1(8), b2(9) ,b3(3)/元素C(3) , C (5), C(6), C(7, 8), C( ),C( )26为构造函数指定实参的方式为构造函数指定实参有三种形式:class A; /假设A的构造函数参数类型为char *A a1(“obejct1 of A”);A a2 = A(“obejct1 of A”);A a3 = “obejct3 of A”; /只能被用于单个实参的情形假设class B有一个无参构造函数B( ),我们可以写B b1;B b2 = B(
25、);B b3( ); /这样对吗?判断一个类是否需要自定义构造函数一个准则:是否需要传递参数如果有只读成员,引用成员:必须在成员初始化列表里初始化,我们必须自定义构造函数,否则无法初始化这两种成员如果有对象成员(注意不是对象指针):必须在成员初始化列表初始化。如果对象成员的初始化必须带参数,我们当然必须自定义构造函数,否则我们是没有机会传递参数的。(如果对象成员的初始化可以不带参数,那我们可以不自定义构造函数,因为我们不需要传递参数,系统会自动地初始化)。如果基类的构造也必须传递参数,道理同上,我们也必须自定义构造函数。自定义的构造函数是否必须带参数?不是必须,因为我们仅仅需要一个传递参数的机会。28什么叫无参构造函数(缺省构造函数)无参(缺省构造函数)是指不需要用户指定实参就能被调用的构造函数。这并不意味着它不能接受实参。下面每一个都是无参(缺省)构造函数。 A:A() A:(int i = 0) A:(int i = 0, int j = 0) 当一个类没有定义构造函数时,编译器会为你提供一个缺省构造函数当你自己定义了构造函数,编译器不再为你提供缺省构造函数因此,当你自定义了一个带参数的构造函数时,你最好再加上一个无参构造函数。为什么?293.7类的存储空
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 中外建筑史知到课后答案智慧树章节测试答案2025年春吉林电子信息职业技术学院
- 中西医结合耳鼻咽喉科学知到课后答案智慧树章节测试答案2025年春湖南中医药大学
- 2017-2018学年高中化学必修2课时训练第二章第一节化学能与热能
- 2017-2018学年人教A版高中数学选修2-2课后提升训练二十二321复数代数形式的加减运算及其几何意义
- 2025年拖拉机及农林牧渔用挂车项目发展计划
- 2017-2018学年人教A版高中数学选修2-3检测第三章统计案例能力深化提升
- 2025年原油降凝降粘剂项目合作计划书
- 天线近场测试仪系统总控软件2
- 乙方提供材料合同范例
- 板模板施工方案
- 道路施工导改及施工方案
- 《实数》单元作业设计
- (word完整版)教师个人简历模板
- 专题11 以小见大-【帮作文】初中语文之从课文中学习写作 课件(共25张PPT)
- 天溯EMS能源管理系统V1.3安装配置手册
- 互联网公司劳动合同
- 二级建造师之二建建设工程施工管理强化训练打印大全
- 吉美版四年级综合实践活动下册全册表格简约式教案教学设计
- 2023河南对口高考计算机类基础课试题
- 幼儿园大班幼小衔接主题活动策划《我们要上学啦》教育PPT模板
- 四川省2022年普通高等学校高职教育单独招生文化考试(普高类)数学试题(原卷版)
评论
0/150
提交评论