第9讲拷贝构造函数及对象成员 教学目的与要求: 了解对象的初始化及深拷贝和浅拷贝 掌握拷贝构造函数的定义和使用及含有对象成员类的 定义和使用。 教学内容提要: 1、拷贝构造函数; 2、对象成员 教学重点:拷贝构造函数的定义和使用。 教学难点:含有对象成员类的定义和使用 教学进度:P71~P73,P97~P99 教学过程
•教学目的与要求: 了解对象的初始化及深拷贝和浅拷贝。 掌握拷贝构造函数的定义和使用及含有对象成员类的 定义和使用。 •教学内容提要: 1、 拷贝构造函数; 2、对象成员; 教学重点:拷贝构造函数的定义和使用。 •教学难点:含有对象成员类的定义和使用。 •教学进度:P71~P73, P97~P99 •教学过程: 第 9 讲 拷贝构造函数及对象成员
(91拷贝构造函数】 1为什么要引入拷贝构造函数? int x=10: Int y-x; student zh(“ zhang”,’m’,20); student i=zh: 当用一个对象去初始化同类的另一个对象时需要调用 拷贝构造函数,为创建的对象申请所需的内存空间, 并已知对象的数据成员去初始化该对象的数据成员。 2拷贝构造函数定义 拷贝构造函数:函数名与类名相同,没有返回类型, 且只能有一个对该类对象的引用的参数的成员函数
1.为什么要引入拷贝构造函数? 2.拷贝构造函数定义 int x=10; int y=x; student zh(“zhang”,’m’,20); student li=zh; 当用一个对象去初始化同类的另一个对象时需要调用 拷贝构造函数,为创建的对象申请所需的内存空间, 并已知对象的数据成员去初始化该对象的数据成员。 【9.1 拷贝构造函数】 拷贝构造函数:函数名与类名相同,没有返回类型, 且只能有一个对该类对象的引用的参数的成员函数
格式::(& 函数体} Ba]: student: student(student p) strcpy(name p name); sexpsex, age-page
格式:::( &) { 函数体} 例: student :: student(student & p) { strcpy(name , p.name); sex=p.sex; age=p.age; }
3拷贝构造函数的调用时刻: 个对象去初始化另一个对象时,系统会自动调 用拷贝构造函数。 概括起来有三种场合: 1)、声明并初始化对象变量时; 2)、对象作为函数参数时; 3)、对象作为函数返回值时;
3. 拷贝构造函数的调用时刻: 一个对象去初始化另一个对象时,系统会自动调 用拷贝构造函数。 概括起来有三种场合: • 1)、声明并初始化对象变量时; • 2)、对象作为函数参数时; • 3)、对象作为函数返回值时;
例9.1 Tpiont: Piont(Piont include &p) class Piont i x-p.X, y-p y cout<<”copy public: constrictor called\n”; Piont(int ix, int iy) void funI(Piont q) XIX 9 y=ly, cout<<"In function cout<” constructor called\n”,; funl(n”; Piont(piont p) Piont( Piont fun20 {cout<“ Destructorcalled\n”;} i Piont T(10, 20) int xcordo return x; j return T int ycordo i return y private: int x, y;
#include class Tpiont { public: Tpiont(int ix, int iy) { x=ix ; y=iy; cout<<”constructor called\n”; } Tpiont(Tpiont & p); ~Tpiont() { cout<< “Destructorcalled\n”; } int xcord() {return x; } int ycord() {return y; } private: int x, y; }; Tpiont::Tpiont(Tpiont & p) { x=p.x; y=p.y; cout<<”copy constrctor called\n”; } void fun1(Tpiont q) { cout<<”In functiont fun1()\n”; } Tpiont fun2() { Tpiont T(10,20); return T; } 例 9.1
void main( piont pI(4,9),p2(0,0) Piont p3(pD); cout<<”p3=(”p3xord0<,<p3yord0<<”)n”; fun1(p3) p2=fun20; 4默认的拷贝构造函数: 当类定义体中没有定义拷贝构造函数,C+十系统会自动提供 个默认的拷贝构造函数。 功能: 只能完成存储空间的分配以及实现一个数据成员到一个数据成员 的复制
void main() { Tpiont p1(4,9),p2(0,0); Tpiont p3(p1); cout<<”p3=(”<<p3.xcord()<<’,’<<p3.ycord()<<”)\n”; fun1(p3); p2=fun2(); } 4.默认的拷贝构造函数: 当类定义体中没有定义拷贝构造函数,C++系统会自动提供一 个默认的拷贝构造函数。 功能: 只能完成存储空间的分配以及实现一个数据成员到一个数据成员 的复制
5浅拷贝和深拷贝数: 浅拷贝:创建P2对象时,对象P1被复制给P2,但资 源并没有复制,因此P1和P2指向同一个资源。 例9.2 class person pl pname public: person(char pn) i pname=new charlstrlen(pn)+1l if(pname!=0) i strcpy(pname, pn); p2pname personi delete lpname; private: char * pname; void mainO { person pl(“ randy”); person p2=pl;
5.浅拷贝和深拷贝数: 浅拷贝:创建P2对象时,对象P1被复制给P2,但资 源并没有复制,因此P1和P2指向同一个资源。 class person { p1.pname public: person(char *pn) { pname=new char[strlen(pn)+1]; if(pname!=0) { strcpy(pname, pn);} p2.pname } ~person() { delete []pname; } private: char *pname; }; void main() { person p1(“randy”); person p2=p1; } 例 9.2
深拷贝:创建P2对象时,对象P1被复制给P2, 同时其资源也作了复制,因此P1和P2指向不同的资源。 在上例的基础上添加一个拷贝构造函数: person: person (person p) pl pname pname=new char [strlen(p pname)+1] if(pname!=0) pZ. pname I strcpy (pname, p. pnamne
深拷贝:创建P2对象时,对象P1被复制给P2, 同时其资源也作了复制,因此P1和P2 指向不同的资源。 在上例的基础上添加一个拷贝构造函数: person::person(person & p) p1.pname { pname=new char[strlen(p.pname)+1]; if(pname!=0) p2.pname { strcpy(pname,p.pnamne); } }
(92对象成员】 (、什么是对象成员 对象成员:在类定义体中使用另一类的对象作为 本类的数据成员。 class DAte /. class student i public private: char names char sex: TDate birthday;// birthday为对象成员, //它是 DAte的对象
1、什么是对象成员 对象成员:在类定义体中使用另一类的对象作为 本类的数据成员。 class TDate { //… }; class student { public: //… private: char*name; char sex; TDate birthday; //birthday为对象成员, //它是TDate的 对象 }; 【9.2 对象成员】
2、对象成员的特征 1)对于带对象成员的类的对象创建时,应先调用对象成员所 属类的构造函数,然后是本类中的构造函数。 2)对于带对象成员的类的对象撤消时,应先调用本类中的析 构函数,然后是对象成员所属类的析构函数。 )对于对象成员所属类Y的构造函数带有不可缺省的参数时, 则含有对象成员的类x的构造函数的定义形式必须如下: class X 类名1对象成员名1; 类名n对象成员名n; 一般来说,类X的构造函数的定义形式为: k:X(形参表0):对象成员名1(形参表1),… 对象成员名i(形参表1,…,对象成员名n(形参表n) //.构造函数体
1)对于带对象成员的类的对象创建时,应先调用对象成员所 属类的构造函数,然后是本类中的构造函数。 2)对于带对象成员的类的对象撤消时,应先调用本类中的析 构函数,然后是对象成员所属类的析构函数。 3)对于对象成员所属类Y的构造函数带有不可缺省的参数时, 则含有对象成员的类X的构造函数的定义形式必须如下: class X { 类名1 对象成员名1; … 类名n 对象成员名n; }; 一般来说,类X的构造函数的定义形式为: X::X(形参表0):对象成员名1(形参表1),…, 对象成员名i(形参表i) ,…,对象成员名n(形参表n) { // …构造函数体 } 2、对象成员的特征