C++面向对象程序设计.ppt_第1页
C++面向对象程序设计.ppt_第2页
C++面向对象程序设计.ppt_第3页
C++面向对象程序设计.ppt_第4页
C++面向对象程序设计.ppt_第5页
已阅读5页,还剩103页未读 继续免费阅读

下载本文档

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

文档简介

第3章类和对象3 1类的构成3 2成员函数的定义3 3对象的定义和使用3 4构造函数与析构函数3 5对象的赋值与复制3 6自引用指针this3 7C 的string类 本章主要内容 3 1类的构成3 1 1从结构体到类3 1 2类的构成 本节主要内容 3 1 1从结构体到类1 结构体的扩充例如下面声明了一个日期结构体 structDate intyear 年intmonth 月intday 日 C语言结构体一般格式如下 struct结构名 数据 例3 1有关日期结构体的例子 includeusingnamespacestd structDate 声明了一个名为Date的结构体intyear intmonth intday intmain Datedate1 date1 year 2010 可以在结构体外直接访问数据yeardate1 month 8 可以在结构体外直接访问数据monthdate1 day 25 可以在结构体外直接访问数据daycout date1 year date1 month date1 day endl return0 程序的运行结果如下 2010 8 25 C语言中的结构体缺点 结构体变量可以在结构体外直接访问数据 在C结构体中的数据是很不安全的 C 中引入了类的概念 克服了C结构体的缺点 C 中引入了类的概念 它不仅可以含有数据 而且还可以含有函数 类中的数据和函数 分别称作数据成员和成员函数 类声明的简化格式如下 class类名 数据函数 类的声明由关键字class打头 后跟类名 花括号中是类体 以一个分号 结束 类声明的简化格式如下 class类名 数据成员函数函数 3 1 2类的构成在类中 数据成员和成员函数分别属于private部分 和public部分 数据成员和成员函数一般也统称为类的成员 类声明的一般格式如下 class类名 public 公有数据成员 公有成员函数 private 私有数据成员 私有成员函数 公有成员既可被类内的成员函数访问 也可被类的外部访问 是类与外界的接口 私有成员只能被类内的成员函数访问 而类外部的任何访问都是非法的 用一个类Date来描述日期 其形式如下 classDate public voidsetDate inty intm intd 公有成员函数voidshowDate 公有成员函数private intyear 私有数据成员intmonth 私有数据成员intday 私有数据成员 私有数据成员year month和day只能由内部成员函数访问 在类的外部无法访问 保护了私有数据的安全 设置日期成员函数setDate和日期显示成员函数showDate都是公有的成员函数 类外部对类Date的数据进行操作 只能通过这两个函数来实现 说明 1 除了private和public之外 类中的成员还可以用另一个关键字protected来说明 被protected说明的数据成员和成员函数称为保护成员 类声明的完整格式如下 class类名 public 公有数据成员 公有成员函数 protected 保护数据成员 保护成员函数 private 私有数据成员 私有成员函数 保护成员可以由本类的成员函数访问 也可以由本类的派生类的成员函数访问 而类外的任何访问都是非法的 将在第5章详细介绍 2 对一个具体的类来讲 类声明格式中的3个部分并非一定要全有 但至少要有其中的一个部分 一般情况下 一个类的数据成员应该声明为私有成员 成员函数声明为公有成员 这样 内部的数据整个隐蔽在类中 在类的外部根本就无法看到 使数据得到有效的保护 3 类声明中的private protected和public三个关键字可以按任意顺序出现任意次 但是 如果把所有的私有成员 保护成员和公有成员归类放在一起 程序将更加清晰 4 C 规定 在默认情况下 即没有指定成员是私有 保护或公有时 类中的成员是私有的 例3 2将例3 1中的结构体struct改为类class includeusingnamespacestd classDate 将例3 1中的结构体struct改为类classintyear 私有数据成员intmonth 私有数据成员intday 私有数据成员 intmain Datedate1 date1 year 2010 错误 在类外不能访问私有数据成员yeardate1 month 8 错误 在类外不能访问私有数据成员monthdate1 day 25 错误 在类外不能访问私有数据成员daycout date1 year date1 month date1 day endl 错误 不能访问私有数据成员return0 私有成员只能被类内的成员函数访问 而类外部的任何访问都是非法的 如何才能访问类中的私有数据成员呢 将在3 2节作详细的介绍 include 例3 1有关日期结构体的例子 usingnamespacestd structDate 声明了一个名为Date的结构体intyear 公有的数据成员intmonth 公有的数据成员intday 公有的数据成员intmain Datedate1 date1 year 2010 可以在结构体外直接访问数据yeardate1 month 8 可以在结构体外直接访问数据monthdate1 day 25 可以在结构体外直接访问数据daycout date1 year date1 month date1 day endl return0 程序的运行结果如下 2010 8 25 在默认情况下 结构体中的成员是公有的 因此 例3 1中数据成员year month和day默认为是公有的 结构体外的变量date1能够对它们直接进行访问 5 不能在类声明中给数据成员赋初值 例如 classabc private chara q 错误intb 33 错误public C 规定 只有在对象定义之后才能给数据成员赋初值 3 2成员函数的定义3 2 1普通成员函数的定义3 2 2内联成员函数的定义 本节主要内容 3 2 1普通成员函数的定义将成员函数以普通成员函数 即非内联的成员函数 的形式进行定义 在类声明中只给出成员函数的原型 而将成员函数的定义放在类外部 例如 Student 成员函数名 参数表 成员函数在类外定义的一般形式是 返回值类型类名 成员函数名 参数表 函数体 在类名和成员函数名之间应加上作用域运算符 classStudent 学生类的定义 1private intnumber floatscore public voidinput intnumber1 floatscore1 函数原型1 输入成绩voidmodify floatscore1 函数原型2 修改成绩voidprint 函数原型3 打印成绩 voidStudent input intnumber1 floatscore1 函数定义1 number number1 score score1 voidStudent modify floatscore1 函数定义2 score score1 voidStudent print 函数定义3 cout nnumber number score score 在类声明中只给出成员函数的原型 而将成员函数的定义放在类外部 在函数名前应加上类名和作用域运算符 说明 1 在类声明中 成员函数原型的参数表中可以不说明参数的名字 而只说明它们的类型 例如 voidmodify floatscore1 但是 在类外定义成员函数时 不但要说明参数表中参数的类型 还必须要指出其参数名 例如 voidStudent modify floatscore1 score score1 2 采用 在类声明中只给出成员函数的原型 而将成员函数的定义放在类的外部 的定义方式 是C 程序设计的良好习惯 3 2 2内联成员函数的定义 1 隐式声明将成员函数直接定义在类的内部 例如 classStudent 学生类的定义 2private intnumber floatscore public voidinput intnumber1 floatscore1 定义成员函数 number number1 score score1 voidmodify floatscore1 定义成员函数 score score1 voidprint 定义成员函数 cout nnumber number score score 将成员函数直接定义在类内部 编译时是作为内联函数的方式来处理 内联函数隐式定义 2 显式声明在类声明中只给出成员函数的原型 而成员函数的定义放在类外部 但在类外部成员函数的定义前冠以关键字 inline 使它起到内联函数的作用 classStudent private intnumber floatscore public voidinput intnumber1 floatscore1 inlinevoidStudent input intnumber1 floatscore1 number number1 score score1 成员函数的原型 冠以关键字 inline 使用inline定义内联函数时 可以在声明函数原型和定义函数时同时写inline 也可以在其中一处声明inline 效果是相同的 都能按内联函数处理 但是 必须将类的声明和内联成员函数的定义都放在同一个文件 或同一个头文件 中 否则编译时无法进行代码置换 classStudent 学生类的定义 3private intnumber floatscore public inlinevoidinput intnumber1 floatscore1 函数原型1inlinevoidmodify floatscore1 函数原型2inlinevoidprint 函数原型3 inlinevoidStudent input intnumber1 floatscore1 number number1 函数定义1score score1 inlinevoidStudent modify floatscore1 score score1 函数定义2inlinevoidStudent print 函数定义3 cout nnumber number score score 冠以关键字 inline 3 3对象的定义和使用3 3 1类与对象的关系3 3 2 对象的定义3 3 3对象中成员的访问3 3 4类的作用域和类成员的访问属性 本节主要内容 3 3 1类与对象的关系在C 中 类与对象间的关系 可以用数据类型int和整型变量i之间的关系来类比 类类型和int类型均代表的是一般的概念 而对象和整型变量却是代表具体的东西 3 3 2 对象的定义定义对象可以用以下两种方法 方法1 在声明类的同时 直接定义对象 即在声明类的右花括号 后 直接写出属于该类的对象名表 例如 classStudent stu1 stu2 在声明类Student的同时 直接定义对象stu1和stu2 方法2 声明了类之后 在使用时再定义对象 其一般形式如下 classStudent Studentstu1 stu2 在使用时再定义对象 此时定义了类Student的两个对象stu1和stu2 说明 声明了一个类便声明了一种类型 这时没有给它分配存储空间 只有定义了对象后 系统才为对象分配存储空间 类名对象名1 对象名2 3 3 3对象中成员的访问不论是数据成员 还是成员函数 只要是公有的 在类的外部可以通过类的对象进行访问 访问对象中的成员通常有以下三种方法 1 通过对象名和对象选择符访问对象中的成员其一般形式是 其中 叫做对象选择符 简称点运算符 对象名 数据成员名或对象名 成员函数名 实参表 include 学生类的完整程序usingnamespacestd classStudent private intnumber floatscore public voidinput intnumber1 floatscore1 输入学生成绩voidmodify floatscore1 修改学生成绩voidprint 打印学生成绩 voidStudent input intnumber1 floatscore1 number number1 score score1 voidStudent modify floatscore1 score score1 voidStudent print cout nnumber number score score intmain Studentstu1 stu2 stu1 input 9901 95 stu2 input 9902 75 stu1 print stu2 print stu1 modify 85 5 stu1 print stu2 print return0 stu1 number 9901 stu1 score 95stu2 number 9902 stu2 score 75 stu1 score 85 5 运行结果 number 9901score 95number 9902score 75number 9901score 85 5number 9902score 75 include 例3 3 1通过对象名和对象选择符访问对象中的成员 usingnamespacestd classDate public voidsetDate inty intm intd voidshowDate private intyear intmonth intday voidDate setDate inty intm intd year y month m day d voidDate showDate cout year month day endl intmain Datedate1 cout Date1setandoutput endl date1 setDate 2010 4 28 date1 showDate return0 调用对象date1的公有成员函数setDate 给date1的私有数据成员赋值 调用对象date1公有成员函数showDate 显示date1的私有数据成员 程序运行结果如下 Date1setandoutput 2010 4 28 说明 在类外只能访问公有 public 成员 而不能访问私有 private 成员 如果将例3 3中的主程序改成下面的形式 将出现编译错误 intmain Datedate1 date1 year 2010 date1 month 8 date1 day 25 cout date1 year date1 month date1 day endl return0 错误 在类的外部 对象date1不能访问私有数据成员year month和day 2 通过指向对象的指针访问对象中的成员此时 访问此对象的成员时 不能用 操作符 而应使用 操作符 例如 classDate public intyear Dated ptr 定义对象d和指向类Date的指针变量ptrptr 输出ptr指向对象中的成员year d year ptr year三者是等价的ptr year 3 通过对象的引用访问对象中的成员如果为一个对象定义了一个引用 也就是为这个对象起了一个别名 例如 classDate public intyear Dated1 定义类Date的对象d1Date 输出对象d2中的数据成员year 由于d2是d1的引用 即d2和d1占有相同的存储单元 因此d2 year和d1 year是相同的 3 3 4类的作用域和类成员的访问属性所谓类的作用域就是指在类的声明中的一对花括号所形成的作用域 一个类的所有成员都在该类的作用域内 在类的作用域内 一个类的任何成员函数成员可以不受限制地访问该类中的其他成员 而在类作用域之外 对该类的数据成员和成员函数的访问则要受到一定的限制 有时甚至是不允许的 这主要与类成员的访问属性有关 类成员有二种访问属性 公有属性和私有属性 说明为公有的成员不但可以被类中成员函数访问 还可在类的外部 通过类的对象进行访问 说明为私有的成员只能被类中成员函数访问 不能在类的外部 通过类的对象进行访问 换一种说法 类内部的成员函数可以访问类的所有成员 没有任何限制 类外部的对象可以访问类的公有成员 不能访问类的私有成员 classSample private inti 私有成员public intj 公有成员voidset inti1 intj1 公有成员 i i1 类的成员函数可以访问类的私有成员ij j1 类的成员函数可以访问类的公有成员j intmain Samplea 定义类Sample的对象aa set 3 5 cout a i endl cout a j endl return0 非法 类Sample的对象a不能访问类的私有成员i 在类外 类Sample的对象a可以访问公有成员函数set 合法 类Sample的对象a能够访问类的公有成员j 分析以下程序段 一般而言 公有成员是类的对外接口 而私有成员是类的内部数据和内部实现 不希望外界访问 3 4构造函数与析构函数3 4 1对象的初始化和构造函数3 4 2用成员初始化表对数据成员初始化3 4 3析构函数3 4 4默认的构造函数和默认的析构函数3 4 5带默认参数的构造函数3 4 6构造函数的重载 本节主要内容 3 4 1对象的初始化和构造函数与使用变量一样 对象时也应该 先定义 后使用 在定义对象时 对数据成员赋初值 称为对象的初始化 C 规定 类声明体中不能给数据成员直接赋初值 下面的写法是错误的 classDate private intyear 2010 错误intmonth 6 错误intday 16 错误 对象的初始化常采用以下两种方法 1 调用普通的成员函数来完成2 调用构造函数来完成 classDate public voidsetDate inty intm intd voidshowDate private intyear intmonth intday intmain Datedate1 date1 setDate 2010 4 28 return0 调用对象date1的公有成员函数setDate 给date1的私有数据成员赋初值 初始化后 Date1 year 2010Date1 month 4Date1 day 28 1 用普通成员函数对对象进行初始化 在建立对象的时 采用构造函数给数据成员赋初值 通常有以下两种形式 形式1 类名对象名 实参表 这里的 类名 与构造函数名相同 实参表 是为构造函数提供的实际参数 2 用构造函数对对象进行初始化 构造函数是一种特殊的成员函数 它主要用于 1 为对象分配空间 2 为对象的数据成员进行初始化 3 其他指定的任务 include 例3 5 1usingnamespacestd classDate public Date inty intm intd 声明构造函数Date的原型voidshowDate private intyear intmonth intday Date Date inty intm intd 定义构造函数Date year y month m day d inlinevoidDate showDate cout year month day endl intmain Datedate1 2010 4 28 date1 showDate return0 3 定义类Date的对象date1 调用构造函数 给对象date1的数据成员赋初值 2 构造函数可以有任意类型的参数 但不能具有返回类型 1 构造函数的名字必须与类名相同 通常 利用构造函数建立对象有以下二种方法 1 一般形式为 类名对象名 实参表 例如 complexA 1 1 2 2 类名对象名实参表 在建立对象的时 采用构造函数对对象进行初始化 通常有以下两种形式 形式1 例如 Datedate1 2010 4 28 类名对象名实参表 建立对象时 编译系统会自动地调用构造函数 对对象进行初始化 类名对象名 实参表 形式2 其一般语法形式为 例如 Date pdate newDate 2010 4 28 类名 指针变量名 new类名 实参表 指针pdate指向该对象的地址对象名 匿名对象 或称对象名是 pdate 此时 应使用 来访问对象的成员 而不是 类名 指针变量名 new类名 实参表 将例3 5 1的主函数改成用这种方法来实现 intmain Date pdate newDate 2010 4 28 pdate showDate deletepdate return0 利用构造函数创建对象的另一种方法 用指针和new来实现 说明 1 构造函数的名字必须与类名相同 否则编译程序将把它当作一般的成员函数来处理 2 构造函数没有返回值 在声明和定义构造函数时 是不能说明它的类型的 甚至说明为void类型也不行 例如上述构造函数不能写成voidDate inty intm intd 说明为void类型也不行 3 与普通的成员函数一样 构造函数的函数体可写在类体内 也可写在类体外 如例3 5 1中的类Date可以声明如下 classDate public Date inty intm intd 构造函数定义在类内 year y month m day d voidshowDate cout year month day endl private intyear intmonth intday 构造函数的函数体也可写在类体外 4 构造函数一般声明为公有成员 但它不需要也不能像其他成员函数那样被显式地调用 它是在定义对象的同时被自动调用的 例如 下面的用法是错误的 date1 Date 2010 4 28 5 构造函数可以是不带参数的 例如 classA private intx public A x 50 intmain Aa 构造函数可以不带参数 定义类A的对象a时 调用不带参数的构造函数给数据成员x赋初值50 3 4 2用成员初始化表对数据成员初始化 classA inti floatf public A inti1 floatf1 i i1 f f1 classA inti floatf public A inti1 floatf1 i i1 f f1 在构造函数中一般用赋值语句对数据成员的初始化进行 C 还提供另一种初始化数据成员的方法 用成员初始化列表来实现对数据成员的初始化 带有成员初始化列表的构造函数的一般形式如下 成员初始化列表的一般形式为 类名 构造函数名 参数表 成员初始化列表 构造函数体 数据成员名1 初始值1 数据成员名2 初始值2 include 例3 6usingnamespacestd classDate public Date inty intm intd 声明构造函数的原型voidshowDate private intyear intmonth intday Date Date inty intm intd year y month m day d voidDate showDate cout year month day endl intmain Datedate1 2010 4 28 定义类Date的对象date1date1 showDate return0 定义构造函数Date 使用成员初始化表对数据成员初始化 运行结果如下 2010 4 28 说明 数据成员是按照它们在类中声明的顺序进行初始化的 与它们在成员初始化列表中列出的顺序无关 练习1写出以下程序的运行结果 includeusingnamespacestd classD intmem1 intmem2 public D inti mem1 i mem2 mem1 1 cout mem1 mem1 endl cout mem2 mem2 endl voidmain Dd 15 相当于 mem1 i mem2 mem1 1 运行结果为 mem1 15mem2 16 includeusingnamespacestd classD intmem1 intmem2 public D inti mem2 i mem1 mem2 1 cout mem1 mem1 endl cout mem2 mem2 endl voidmain Dd 15 相当于 mem2 i mem1 mem2 1 请问 运行结果 mem1 16mem2 15实际运行结果 mem1 858993459mem2 15 原因 不是按照构造初始化表的顺序对数据成员进行初始化 而是按照数据成员在类里被声明的顺序进行初始化 练习2 includeusingnamespacestd classD intmem1 intmem2 public D inti mem2 i mem1 mem2 1 cout mem1 mem1 endl cout mem2 mem2 endl voidmain Dd 15 初始化过程 1 mem1 mem2 1 随机数2 mem2 i 15 程序结果如下 mem1 858993459mem2 15 解决方法 练习2 分析错误原因 练习2 includeusingnamespacestd classD intmem2 intmem1 public D inti mem2 i mem1 mem2 1 cout mem1 mem1 endl cout mem2 mem2 endl voidmain Dd 15 将mem1和mem2交换 运行结果为 mem1 16mem2 15 3 4 3析构函数析构函数也是一种特殊的成员函数 它执行与构造函数相反的操作 通常用于执行一些清理任务 主要有 1 释放分配给对象的内存空间 2 其他指定的任务 classStudent 带构造函数的学生类private intnumber floatscore public Student intnumber1 floatscore1 Student cout destructing Student Student intnumber1 floatscore1 number number1 score score1 构造函数 析构函数 classStudent private intnumber floatscore public Student intnumber1 floatscore1 Student cout destructing Student Student intnumber1 floatscore1 number number1 score score1 析构函数与类名相同 但它前面必须加一个波浪号 析构函数没有参数 也没有返回值 当撤消对象时 编译系统会自动地调用析构函数 析构函数有以下一些特点 1 析构函数名与类名相同 但它前面必须加一个波浪号 2 析构函数不返回任何值 在定义析构函数时 是不能说明它的类型的 甚至说明为void类型也不行 3 析构函数没有参数 因此它不能被重载 一个类可以有多个构造函数 但是只能有一个析构函数 4 撤销对象时 编译系统会自动地调用析构函数 include 例3 7含有构造函数和析构函数的Date类 usingnamespacestd classDate public Date inty intm intd 声明构造函数 Date 声明析构函数voidsetDate inty intm intd voidshowDate private intyear intmonth intday Date Date inty intm intd 定义构造函数 cout constructing endl year y month m day d Date Date 定义析构函数 cout destruting endl voidDate setDate inty intm intd year y month m day d inlinevoidDate showDate cout year month day endl intmain Datedate1 2010 4 28 date1 showDatereturn0 程序运行结果如下 constructing 2010 4 28destruting 定义类Date的对象date1 调用date1的构造函数 初始化对象date1 说明 在以下情况 当对象的生命周期结束时 析构函数会被自动调用 如果定义了一个全局对象 则在程序流程离开其作用域时 如main函数结束或调用exit函数 时 调用该全局对象的析构函数 如果一个对象被定义在一个函数体内 则当这个函数结束时 该对象的析构函数被自动调用 若一个对象是使用new运算符动态创建的 在使用delete运算符释放它时 delete会自动调用析构函数 include 例3 8较完整的学生类示例 includeusingnamespacestd classStudent public Student char name1 char stu no1 floatscore1 声明构造函数 Student 声明析构函数voiddisp 成员函数 用于显示数据private char name char stu no floatscore 姓名 学号 成绩Student Student char name1 char stu no1 floatscore1 name newchar strlen name1 1 strcpy name name1 stu no newchar strlen stu no1 1 strcpy stu no stu no1 score score1 定义构造函数 Student Student 定义析构函数 delete name delete stu no voidStudent disp cout name name endl cout stu no stu no endl cout score score endl intmain Studentstu1 Liming 20080201 90 stu1 disp Studentstu2 Wangfun 20080202 85 stu2 disp return0 定义类Student的对象stu1 调用构造函数 初始化对象stu1 定义类Student的对象stu2 调用构造函数 初始化对象stu2 运行结果如下 name Limingstu no 20080201score 90name Wangfunstu no 20080202score 85 3 4 4默认的构造函数和默认的析构函数1 默认的构造函数如果没有在类中定义构造函数 则编译系统自动地生成一个默认的构造函数 例如 编译系统为类Date生成下述形式的构造函数 Date Date 这个默认的构造函数 不带任何参数 只能为对象开辟一个存储空间 而不能给对象中的数据成员赋初值 例3 9一个没有对数据成员赋初值的例子 includeusingnamespacestd classMyclass public intno intmain Myclassa cout a no endl return0 运行结果如下 858993460 不难看出 本例的运行结果是一个随机数 在实际使用时可能会造成错误 说明 1 对没有定义构造函数的类 其公有数据成员可以用初始值表进行初始化 请看以下例子 例3 10用初始值表初始化公有数据成员 includeusingnamespacestd classMyclass public charname 10 intno intmain Myclassa chen 25 cout a name a no endl return0 运行结果如下 chen25 用初始值表初始化公有数据成员 2 只要一个类定义了构造函数 不一定是无参构造函数 系统将不再给它提供默认的构造函数 includeclassLocation private intX Y public voidInit intinitX intinitY X initX Y initY intGetX returnX intGetY returnY intmain LocationA3 A3 Init 785 980 cout A3 GetX A3 GetY endl return0 类中没有用户定义的构造函数 C 编译系统自动地生成一个默认的构造函数 定义对象时 就调用这个自动生成的默认的构造函数 运行结果 785980 include 例3 10分析下列程序的运行结果 usingnamespacestd classDate public Date inty intm intd 带有参数的构造函数voidsetDate inty intm intd voidshowDate private intyear intmonth intday Date Date inty intm intd year y month m day d voidDate setDate inty intm intd year y month m day d inlinevoidDate showDate cout year month day endl intmain Datedate1 date1 setDate 2002 11 14 date1 showDate return0 程序的运行结果是 2002 11 14 错误的原因是 当类中定义了带有参数的构造函数后 系统将不再给它提供默认的构造函数 因此当定义类Date的对象date1时 找不到与之匹配的构造函数 include 例3 10分析下列程序的运行结果 usingnamespacestd classDate public Date inty intm intd 带有参数的构造函数voidsetDate inty intm intd voidshowDate private intyear intmonth intday Date Date inty intm intd year y month m day d voidDate setDate inty intm intd year y month m day d inlinevoidDate showDate cout year month day endl intmain Datedate1 date1 setDate 2002 11 14 date1 showDate return0 方法1 把语句 改为Datedate1 2002 11 14 解决方法 方法2 增加一个如下的构造函数Date 2 默认的析构函数每个类必须有一个析构函数 若没有显式地为一个类定义析构函数 编译系统会自动地生成一个缺省的析构函数 例如 Date Date 当撤消对象时 这个缺省的析构函数将释放分配给对象的内存空间 说明 对于大多数类而言 默认的析构函数就能满足要求 但是 如果在一个对象完成其操作之前需要做一些内部处理 则应该显式地定义析构函数 以完成所需的操作 如例3 8中的析构函数 Student Student delete name 释放由运算符new分配的内存空间delete stu no 释放由运算符new分配的内存空间 3 4 5带默认参数的构造函数在实际使用中 有些构造函数的参数值在大部分情况是相同的 只有在特殊情况下才需要改变它的参数值 例如大学本科的学制一般默认为4年 某大学工科的学费一般默认为每年5000元 计时器的初始值一般默认为0等 这时可以将其定义成带默认参数的构造函数 例如长方体的长 宽 高的默认值均为10 其构造函数的原型可写成 Box inth 10 intw 10 intlen 10 调用此函数时 若省略其中某一实参 C 自动地以默认值作为相应参数的值 include 例3 10 1classBox private intheight width length public Box inth 10 intw 10 intlen 10 intvolume Box Box inth intw intlen height h width w length len intmain Boxbox1 cout box1 box1 volume endl Boxbox2 15 cout box2 box2 volume endl Boxbox3 15 30 cout box3 box3 volume endl Boxbox4 15 30 20 out box4 box4 volume endl return0 含有默认参数的构造函数 在此不再指定参数的默认值 不传递参数 全部用默认值 传递三个参数 只传递一个参数 传递两个参数 运行结果 box1 1000box2 1500box3 4500box1 9000 说明 在一个类中定义了全部是默认参数的构造函数后 不能同时再声明无参数的默认构造函数 或其他重载构造函数 例如在一个类中有以下构造函数的声明 Box inth 10 intw 10 intlen 10 就不能再声明无参数的构造函数 Box 否则 如用下面的语句建立对象Boxbox1 编译系统将无法判断应该调用哪个构造函数 因此产生了二义性 声明全部是默认参数的构造函数 3 4 6构造函数的重载C 允许构造函数重载 以适应不同的场合 这些构造函数之间以它们所带参数的个数或类型的不同而区分 例如 类A具有四个不同的构造函数 classA public A 不带参数的构造函数 A int 只带一个整型参数的构造函数 A int char 带两个参数的构造函数 A float char 带两个参数的构造函数 intmain Ax 调用构造函数A Ay 10 调用构造函数A int Az 10 z 调用构造函数A int char Aw 4 4 w 调用构造函数A float char include 例3 13构造函数重载的示例 usingnamespacestd classRectangle public Rectangle 声明无参数的构造函数Rectangle intlen intwid 声明带有参数的构造函数intarea return length width private intlength width Rectangle Rectangle length 10 width 10 定义无参数的构造函数Rectangle Rectangle intlen intwid 定义带有参数的构造函数 length len width wid intmain Rectanglerec1 定义对象rec1 调用无参数的构造函数cout Theareaofrectangle1is rec1 area endl Rectanglerec2 15 20 定义对象rec2 调用带有参数的构造函数cout Theareaofrectangle2is rec2 area endl return0 程序运行结果如下 Theareaofrectangle1is100Theareaofrectangle2is300 说明 1 使用无参构造函数创建对象时 应该用语句 Rectanglerec1 而不能用语句Rectanglerec1 因为语句 Rectanglerec1 表示声明一个名为rec1的普通函数 此函数的返回值为Rectangle类型 2 在一个类中 当无参数的构造函数和带默认参数的构造函数重载时 有可能产生二义性 例如 classX public X 无参数的构造函数X inti 0 带默认参数的构造函数 intmain Xone 10 正确 调用带默认参数的构造函数Xtwo 它既可以调用无参数的构造函数 也可以调用带默认参数的构造函数 因此产生了二义性 3 5对象的赋值与复制3 5 1对象赋值语句3 5 2拷贝构造函数 本节主要内容 3 5 1对象赋值语句变量之间可以进行赋值 intA B B A 同类型的对象之间也可以进行赋值 对象赋值的一般形式为 当一个对象赋值给另一个对象时 所有的数据成员都会逐位拷贝 对象名1 对象名2 include 例3 14 1usingnamespacestd classABC public voidinit inti intj a i b j voidshow cout a b endl private inta b intmain ABCo1 o2 o1 init 12 34 o2 o1 将对象o1数据成员的值赋给对象o2o1 show o2 show return0 o1 a 12o1 b 34 赋值后的作用 o2 a o1 a o2 b o1 b 运行结果 341234 说明 1 在使用对象赋值语句进行对象赋值时 两个对象的类型必须相同 如对象的类型不同 编译时将出错 2 两个对象之间的赋值 仅仅是对其中的数据成员赋值 而不对成员函数赋值 数据成员是占存储空间的 不同对象的数据成员占有不同的存储空间 而不同对象的成员函数是占有同一个函数代码段 无法对它们赋值 3 5 2拷贝构造函数拷贝构造函数的其作用是 在建立一个新对象时 使用一个已经存在的对象去初始化这个新对象 例如 Pointp2 p1 其作用是 在建立新对象p2时 用已经存在的对象P1去初始化新对象p2 在这个过程中就要调用拷贝构造函数 拷贝构造函数有以下两种 用户自定义的拷贝构造函数 系统自动生成的默认的拷贝构造函数 1 自定义拷贝构造函数自定义拷贝构造函数的一般形式如下 类名 类名 const类名 对象名 拷贝构造函数的函数体 已经存在的对象 下面是一个用户自定义的拷贝构造函数 classpoint intx y public point inta intb 构造函数 x a y b point constpoint p 拷贝构造函数 x 2 p x y 2 p y main pointp1 10 20 pointp2 p1 return0 自定义的拷贝构造函数 下面是一个用户自定义的拷贝构造函数 classpoint intx y public point inta intb 构造函数 x a y b point constpoint p 拷贝构造函数 x 2 p x y 2 p y main pointp1 10 20 pointp2 p1 return0 相当于 constpoint p p1 类似执行以下语句 pointp2 p2 x 2 p1 x p2 y 2 p1 y 下面是一个用户自定义的拷贝构造函数 classpoint intx y public point inta intb 构造函数 x a y b point constpoint p 拷贝构造函数 x 2 p x y 2

温馨提示

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

评论

0/150

提交评论