C++_构造函数与析构函数 (4)

(3) 当函数的返回值是对象,函数执行完成,返回调用者时。

// … Coord fun2() { Coord p1(10,30); return p1; } // 函数的返回值是对象 main() { Coord p2; P2=fun2(); // 函数执行完成,返回调用者时,调用拷贝构造函数 return 0; } 3.4 浅拷贝和深拷贝

所谓浅拷贝,就是由缺省的拷贝构造函数所实现的数据成员逐一赋值,若类中含有指针类型数据, 则会产生错误

为了解决浅拷贝出现的错误,必须显示地定义一个自己的拷贝构造函数,使之不但拷贝数据成员,而且为对象1和对象2分配各自的内存空间,这就是所谓的深拷贝

例2.23 浅拷贝例子 #include<iostream.h> #include<string.h> class Student { public: Student(char *name1,float score1); ~Student(); private: char *name; // 学生姓名 float score; // 学生成绩 }; Student∷Student(char *name1,float score1) { cout<<"Constructing..."<<name1<<endl; name=new char[strlen(name1)+1]; if (name !=0) { strcpy(name,name1); score=score1; } } Student∷~Student() { cout<<"Destructing..."<<name<<endl; name[0]='\0'; delete name; } void main() { Student stu1("liming",90); // 定义类Student的对象stu1 Student stu2=stu1; // 调用缺省的拷贝构造函数 } Constructing... liming Destructing... liming Destructing... 浅拷贝示意图

image

例2.24 深拷贝例子 #include<iostream.h> #include<string.h> class Student { private: char *name; // 学生姓名 float score; // 学生成绩 public: Student(char *name1,float score1); Student(Student& stu); ~Student(); }; Student∷Student(char *name1,float score1) { cout<<"constructing..."<<name1<<endl; name=new char[strlen(name1)+1]; if (name !=0) { strcpy(name,name1); score=score1; } } Student∷Student(Student& stu) { cout<<"Copy constructing..."<<stu.name<<endl; name=new char[strlen(stu.name)+1]; if (name !=0) { strcpy(name,stu.name); score=stu.score; } } Student∷~Student() { cout<<"Destructing..."<<name<<endl; name[0]='\0'; delete name; } void main() { Student stu1("liming", 90); // 定义类Student的对象stu1, Student stu2=stu1; // 调用自定义的拷贝构造函数 } Constructing…liming Copy constructing…liming Destructing…liming Destructing…liming 深拷贝示意图

image

4. 析构函数

析构函数也是一种特殊的成员函数。它执行与构造函数相反的操作,通常用于撤消对象时的一些清理任务,如释放分配给对象的内存空间等。

析构函数有以下一些特点:

① 析构函数与构造函数名字相同,但它前面必须加一个波浪号(~);

② 析构函数没有参数,也没有返回值,而且不能重载。因此在一个类中只能有一个析构函数;

③ 当撤消对象时,编译系统会自动地调用析构函数。 如果程序员没有定义析构函数,系统将自动生成和调用一个默认析构函数,默认析构函数只能释放对象的数据成员所占用的空间,但不包括堆内存空间。

例2.25 重新说明类Date #include <iostream.h> class Date{ public: Date(int y,int m,int d); // 构造函数 ~Date(); // 析构函数 void setDate(int y,int m,int d); void showDate(); private: int year, month, day; }; Date::Date(int y,int m,int d) // 构造函数的实现 { cout<<"constructing..."<<endl; year=y;month=m; day=d; } Date::~Date() // 析构函数的实现 { cout<<"destruting..."<<endl; } void Date::setDate(int y,int m,int d) { year=y;month=m;day=d; } inline void Date::showDate() { cout<<year<<"."<<month<<"."<<day<<endl; } void main() { Date date1(1998,4,28); // 定义类Date的对象date1, // 调用date1的构造函数,初始化对象date1 cout<<"Date1 output1:"<<endl; date1.showDate(); // 调用date1的showDate(),显示date1的数据 date1.setDate(2002,11,14); // 调用date1的setDate(), // 重新设置date1的数据 cout<<"Date1 output2:"<<endl; date1.showDate(); // 调用date1的showDate(),显示date1的数据 } 析构函数被调用的两种情况

1) 若一个对象被定义在一个函数体内,当这个函数结束时,析构函数被自动调用。
2) 若一个对象是使用new运算符动态创建,在使用delete释放时,自动调用析构函数。

【例2.13】 较完整的学生类例子 #include<iostream.h> #include<string.h> class Student { public: Student(char *name1,char *stu_no1,float score1); // 构造 函数 ~Student(); // 析构函数 void modify(float score1); // 修改数据 void show(); // 显示数据 private: char *name; // 学生姓名 char *stu_no; // 学生学号 float score; // 学生成绩 }; Student∷Student(char *name1,char *stu_no1,float score1) { name=new char[strlen(name1)+1]; strcpy(name,name1); stu_no=new char[strlen(stu_no1)+1]; strcpy(stu_no,stu_no1); score=score1; } Student∷~Student() { delete []name; delete []stu_no; } void Student∷modify(float score1) { score=score1; } void Student∷show() { cout<<"\n name: "<<name; cout<<"\n stu_no: "<<stu_no; cout<<"\n score: "<<score; } void main() { Student stu1("Liming","990201",90); // 定义类Student的对象stu1, // 调用stu1的构造函数,初始化对象stu1 stu1.show(); // 调用stu1的show(),显示stu1的数据 stu1.modify(88); // 调用stu1的modify(),修改stu1的数据 stu1.show(); // 调用stu1的show(),显示stu1修改后的数据 } name:Liming stu_no:990201 score:90 name:Liming stu_no:990201 score:88 缺省的析构函数

每个类必须有一个析构函数。

若没有显式地为一个类定义析构函数,编译系统会自动地生成一个缺省的析构函数

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxwps.html