始化该类的另一个对象时。
Coord p2(p1); // 用对象p1初始化对象p2, 拷贝构造函数被调用(代入法)
Coord p3=p1; // 用对象p1初始化对象p3, 拷贝构造函数被调用(赋值法)
- (2) 当函数的形参是类的对象,调用函数,进行形参和实参结合时。
//…
fun1(Coord p) // 函数的形参是类的对象
{
p.print();
}
main()
{
Coord p1(10,20);
fun1(p1); // 当调用函数,进行形参和实参结合时,
调用拷贝构造函数
return 0;
}
- (3) 当函数的返回值是对象,函数执行完成,返回调用者时。
// …
Coord fun2()
{
Coord p1(10,30);
return p1;
} // 函数的返回值是对象
main()
{
Coord p2;
P2=fun2(); // 函数执行完成,返回调用者时,调用拷贝构造函数
return 0;
}
5.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...
浅拷贝示意图
例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
深拷贝示意图
6. 析构函数
析构函数也是一种特殊的成员函数。它执行与构造函数相反的操作,通常用于撤消对象时的一些清理任务,如释放分配给对象的内存空间等。
析构函数有以下一些特点:
- ① 析构函数与构造函数名字相同,但它前面必须加一个波浪号(~);
- ② 析构函数没有参数,也没有返回值,而且不能重载。因此在一个类中只能有一个析构函数;
- ③ 当撤消对象时,编译系统会自动地调用析构函数。 如果程序员没有定义析构函数,系统将自动生成和调用一个默认析构函数,默认析构函数只能释放对象的数据成员所占用的空间,但不包括堆内存空间。
例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:&