一、说在前面
C++的构造函数和析构函数,使类对象能够轻松地 被创建和撤销。构造函数创建类对象,初始化其 成员,析构函数撤销类对象。构造函数和析构函数是类的特殊成员函数。构造函数和析构函数的 实现使C++的类机制得以充分的展示
二、构造函数
(一)类与对象的区别
直接看例子
一个类描述一类事物,描述这些事物所应具有的属性,如人有身高、 体重、文化程度、性别、年龄、民族等。
一个对象是类的一个实例,它具有确定的属性,如张三(人的实例) 身高180cm、体重70kg、大学本科、男、21岁、汉族。 人类只有一个,人类的实例可以有无数个。
对象可以被创建和销毁,但类是无所不在的。
(二)定义对象
属于不同类的对象在不同的时刻、不同的地方分别被建立。全局对象在主函数开始执行前首先被建立,局部对象在程序执行遇到它们的对象定义时才被建立。与定义变量类似,定义对象时,C++为其分配空间。
例如,下面的代码定义了两个类,创建了类的全局对象、局部对象、 静态对象和堆对象:
class Desk //Desk类
{
public:
int weight, high, width, length;
};
class Stool //另一个类:Stool类
{
public:
int weight; high, width, length;
};
Desk da; //全局对象
Stool sa;
void fn()
{
static Stool ss; //静态局部对象
Desk da; //局部对象
//…
}
void main()
{
Stool bs; //局部对象
Desk *pd=new Desk; //堆对象
Desk nd[50]; //局部对象数组
//…
delete pd; //释放堆对象
}
(三)构造函数的需要性
1、变量初始化的方法如下所示: int a=1; int *pa=&a;
2、数组初始化的方法如下所示: int b[ ]={1, 2, 3, 4};
3、结构初始化的方法如下所示:
struct Student
{
int semesHours; //总学时数
float gpa; //平均成绩
};
void fn()
{
Student s={100, 3.5}; //创建结构变量时,初始化
//…
}
4、但是,对类对象来说,如此初始化不行,这是由类的特殊性决定的。 例如,下面的代码企图在对象创建时为其初始化:(这样操作不行不行不行)
class Student
{
public:
//…公共成员函数
protected:
int semesHours; //此处的数据成员是受保护的
float gpa;
};
void fn()
{
Student s={100,3.5}; //error:不能访问
//…
}
类的封装性就体现在一部分数据是不能让外界访问的。所以直接在非成员函数中访问类对象的保护或私有数据是不允许的。
类对象初始化的任务,自然就落在类的成员函数身上,因为它们可以 访问保护和私有数据成员。
(四)使用构造函数初始化对象
1、初始化
C++规定与类同名的成员函数是构造函数,在该类的对象创建时,自动被调用。
例如,下面的代码初始化桌子和凳子类对象:
class Desk
{
public:
Desk() //构造函数定义
{ weight=10; high=5; width=5; length=5;}
protected:
int weight, high, width, length;
};
class Stool
{
public:
Stool() //构造函数定义
{ weight=6; high=3; width=3; length=3;}
protected:
int weight, high, width, length;
};
void fn()
{
Desk da; //自动调用Desk(),创建对象并初始化
Stool sa; //自动调用Stool()
//…
}
构造函数可以放在类的外部定义。看下面这个例子
#include <iostream.h>
class Desk
{
public:
Desk(); //构造函数声明
protected:
int weight, high, width, length;
};
class Stool
{
public:
Stool(); //构造函数声明
protected:
int weight, high, width, length;
};
Desk::Desk() //构造函数定义
{
weight=10; high=5; width=5; length=5;
cout<<weight<<" "<<high<<" "<<width<<" "<<length<<endl;
}
Stool::Stool() //构造函数定义
{
weight=6; high=3; width=3; length=3;
cout<<weight<<" "<<high<<" "<<width<<" "<<length<<endl;
}
void fn()
{
Desk da; //自动调用Desk()
Stool sa; //自动调用Stool()
}
void main()
{
fn();
}
2、构造函数的特点:
(1)它没有返回类型,函数体中也不允许有返回值,但可以有无值返回语句“return;”,看下面这个例子:
3、类的成员可能为另一个类的对象
(1)怎么构造对象?
如果一个类对象是另一个类的数据成员,则在那个类的对象创建所调用的构造函数中,对该 成员(对象)自动调用其构造函数。
(2)看2个例子
例1,组合音响类中包含各个套件类对象
class Recorder{ //…};
class Cdplayer{ //…};
class Amplifier{ //…};
class Tuner{ //…};
class HiFi
{
public:
//…
protected:
Recorder re;
Cdplayer cd;
Amplifier am;
Tuner tu;
};
例2,一个“帮教派对”类TutorPair 中包含有学生类对象和老师类对象
#include <iostream.h>
class Student
{
public:
Student()
{
cout<<"constructing student.\n";
semesHours=100;
gpa=3.5;
}
protected:
int semesHours;
float gpa;
};
class Teacher
{
public:
Teacher()
{
cout<<"constructing teacher.\n";
}
};
class TutorPair
{
public:
TutorPair()
{
cout<<"Constructing tutorpair.\n";
noMeetings=0;
}
protected:
Student student;
Teacher teacher;
int noMeetings;//会晤次数
};
void main()
{
TutorPair tp;
cout<<"back in main.\n";
}