C++课件,从零开始

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

构造函数的特点:




1. 构造函数是成员函数,函数体可写在类体内,也 可写在类体外。 2. 构造函数是一个特殊的函数,该函数的名字与类 名相同,一般声明为public函数,无返回值,不指 定类型,也不需要加void类型声明。 3. 构造函数可以重载,即可以定义多个参数个数或 参数类型不同的构造函数。 4. 程序中不能直接调用构造函数,在创建对象时系 统自动调用构造函数。
class Student{ public: Student(const string& n); // ... }; void fn(Student& s); int main(){ string t=“jenny”; fn(t); // 参数为string,却能匹配Student类型 }
3. 类成员初始化 ( Class Member ຫໍສະໝຸດ Baidunitializations )
数据成员的空间分配是在构造函数被调 用和其过程被执行之间的刹那间完成, 在类中有对象成员时,那个刹那间便是 调用对象所在类的构造函数,以创建对 象空间的时机,左边的程序得到下列运 行结果:
StudentId: 1 Student: Randy
说明先成员构造,后自身构造.成员构 造不见显式调用,而是悄悄调用无参构 造函数.
class StudentID{ int a; public: StudentID(){ a = 1; cout<<“StudentId: "<<a<<"\n"; } }; class Student{ string name; StudentID id; public: Student(string n="noName"){ cout<<“Student: "+ n +"\n"; name = n; } }; int main(){ Student s("Randy"); }
拷贝构造函数


拷贝初始化构造函数是一种特殊的成 员函数,其形参是本类对象的引用。 它的功能是用一个已知的对象来初始 化一个被创建的同类的对象 拷贝初始化构造函数实际上也是构造 函数,它是在初始化时被调用来将一 个已知对象的数据成员的值拷贝给正 在创建的另一个同类的对象。
其特点如下:




成员对象的构造顺序按类中定义的 出现顺序,最后执行自身构造函 数:
class A{ B b; C c; D d; public: A(){} // ... }; int main(){ A a; }
则构造顺序为b>c>d,然后执行A 的构造函数的花括号体{}
构造位置
全局数据区: 全局对象,静态全局对象,静态局部对象,常对象 存放在该数据区 栈区: 局部对象 (根据不同编译器的实现方法,临时对象可能在 栈区,也可能在动态存储区,也可能一部分 在栈区,一部分在动态存储区) 动态存储区(也称堆区): 用new申请的对象 除此之外,还可以指定特殊地址空间,存放对象
它负责资源分配和由此而来的指针修改.
class Person{ char* pName; public: Person(char* pN="noName"){ pName = new char[strlen(pN)+1]; if(pName) strcpy(pName,pN); } Person(const Person& s){ pName = new char[strlen(s.pName)+1]; if(pName) strcpy(pName, s.pName); } ~Person(){ delete[] pName; } };


⑵当一个对象是用new运算符被动态创建 的,在使用delete运算符释放它时,delete 会自动调用析构函数。 5. 如果用户没有编写析构函数,编译系统 会自动生成一个缺省的析构函数。
7. 转型与赋值 ( Conversion & Assignment )
对象转型
一个构造函数 , 含有一个其他数据类型的参数 , 显然 其意义为,用该参数类型的值可以创建本对象 .从 另一方面看,参数类型的值可以转换为本对象.
C++程序设计教程(第二版)
第九章 对象生灭 Chapter 9 Object Birth & Death
第九章内容
1. 2. 3. 4. 5. 6. 7. 构造函数设计 ( Constructor Design ) 构造函数重载 ( Constructor Overload ) 类成员初始化 ( Class Member Initializations ) 构造顺序 ( Constructing Order ) 拷贝构造函数 ( Copy Constructors ) 析构函数 ( Destructors ) 转型与赋值 ( Conversion & Assignment )
1. 该函数名同类名,并且该函数也不被指定 返回类型。 2. 该函数只有一个参数,并且是对某个对象 的引用。 3. 每个类都有各自的拷贝初始化构造函数, 其格式如下所示: <类名>::<类名>(<类名> &<引用名>) 4. 如果类中没有说明拷贝初始化构造函数, 则编译系统自动生成一个具有上述形式的缺 省拷贝初始化构造函数,作为该类的公有成 员。
若类中没有定义构造函数,则系统 会默认定义一个无参空函数:
class Date{ public: // 相当于定义了Date(){} }; int main(){ Date d; // ok // ... }
任何其他的构造函数定义,都将阻止默 认无参空函数的产生: class Date{ public: Date(int y, int m, int d){} // ... }; int main(){ Date d; // error // ... }
给出一个关于日期的类的定义,该类是对日期抽 象,该类的对象是某一个具体的日期

#include “iostream.h” class Date { public: Date(int y, int m, int d) { year=y; month=m; day=d; } void print( ) { cout<<year<<”_”<<month<<”_”<<day<<endl; } private: int year, month, day; }; void main( ) { Date ob(1999,2,12); ob.print( ); }
例外:一次性对象构造 , 没有对象名 , 与强制转 换的形式一致,因而它是一个特定类型的对象.
一、构造函数(功能:创建对象 时,使用给定值将对象初始化)

建立一个对象时,常常需要作某些初始化的 工作(例如对数据赋予初值),C++提供了 一种特殊的成员函数——构造函数 (constructor),这种函数与其它成员不同, 不需要用户发“消息”来激活它,而是在建 立对象时由系统自动执行。构造函数是由用 户定义的,它必须与类名同名,以便系统能 识别它并把它作为构造函数。
Date(const Date& d){}
默认拷贝构造函数体一定是空的.
空拷贝构造函数负责将传递的对象到新创 的对象,做对象本体的位对位拷贝.(甚 至连指针值都相等,即与参数对象拥有 共同的资源) 拷贝构造函数体的工作不负责位对位对象 复制,一般来说,它负责资源分配和由 此而来的指针修改.
拷贝构造函数体的工作不负责位对位对象复制,一般来说,
1. 构造函数设计 ( Constructor Design )
初始化要求:对象与变量的不同在于对象对应 于事物,要求从诞生之时起便有明确的意义. 封装性要求:初始化不是简单的参数与成员对 应,而是联系参数到成员的过程. 构造函数名:该过程产生对象,而不是捆绑对象 的成员函数调用,因而它是特殊的成员函数 形式:与变量的定义形式保持一致.构造函数原 则上不能失败,也没有返回形式
析构函数的特点:
1. 析构函数也是成员函数,函数体可写在类体 内,也可以写在内体外。 2. 析构函数的名字同类名,并在前面加“~”字 符,用来与构造函数加以区别。析构函数不 指定数据类型,并且也没有参数。 3. 一个类中只可能定义一个析构函数,不能重 载。

4. 析构函数可以被调用,也可以系统自动 调用,在下面两种情况,析构函数会被自 动调用: ⑴如果一个对象被定义在一个函数体内,则 当这个函数结束时,该对象的析构函数被 自动调用。
4. 构造顺序 ( Constructing Order )
对象或变量创建的语句行顺 序与运行顺序:
int a=3; if(a==2) Date d; Date e; 则对象创建的语句行顺序为: Date d--->Date e 对象创建的运行顺序为: Date e
同一工程不同代码文件全局对象的创建 没有明确顺序规定. 对策:不要让不同文件的全局对象互为 依赖.因为依赖具有先后性,而其全 局对象的创建不能保证该依赖性发挥 作用. 全局对象在main函数启动之前生成,而 调试则在main函数启动之后. 对策:调试时,应先将全局对象作为局 部对象来运行观察.或者,在构造函 数中添加输出语句来观察运行过程.
5. 拷贝构造函数 ( Copy Constructors )
对象本体与对象实体: 对象本体也是对象主体,对象实体则 还包括属于对象的衍生物,如,某 个人体是人类对象的主体,然而某 人还拥有父母,房产等属于某人的 世系或资产,描述人的属性不仅仅 只是人体数据. 从形式上看,对象除了包括数据成员, 还包括指向数据的指针.
2. 构造函数重载 ( Constructor Overload )
构造函数可以重载,也可以参数默认:
class Date{ public: Date(const string& s); Date(int y=2003, int m=12, int d=1); // ... }; int main(){ Date d(“2006-12-26”); Date e(2000, 12, 25); Date f(2001, 10); Date g(2002); Date h; // ... }
6. 析构函数 ( Destructors )
对象结束其生命时,会被系统 悄悄地销毁 ( 析构 ). 即对象本 体空间与名字脱离关系. 对象结束生命时 , 若对象本体与 对象实体不同 , 则需要人为地 进行资源释放 , 以保证对象本 体失效之前,资源被收回.
定义析构函数的目的:
由于对象本体与实体不同,所以要进 行对象占有资源的释放工作. 一般来说,一个类,若有人为定义的 拷贝构造函数,则也应该定义析构 函数.因为对象创建中有资源要获 得分配,则对象失效前必应先释放 资源.
若要调用对象 成员的有参构 造函数,须显 式调用,见左 边形式.其运 行结果为:
StudentId: 98 Student: Randy StudentId: 0 Student: Jenny
class StudentID{ int a; public: StudentID(int id=0){ a=id; cout<<“StudentId: "<<a<<“\n”; } }; class Student{ string name; StudentID id; public: Student(string n="noName", int ssID=0) :id(ssID),name(n){ cout<<“Student: "<<n<<"\n"; } }; int main(){ Student s("Randy", 98); Student t("Jenny"); }
拷贝构造函数:
以本类对象为常量引用参数的构造函数: class Date{ public: Date(); Date(const Date& d); // . . . }; Date x; //调用无参构造函数 Date y(x); //调用拷贝构造函数
默认拷贝构造函数: 若类中没有定义拷贝构造函数,则系统会 悄悄定义一个默认空拷贝构造函数:
相关文档
最新文档