C++中对象的初始化和清理是两个很重要的问题,因此设计者们采用构造函数和析构函数来解决这两个问题,这两个函数编译器会自动调用,完成对象的初始化和清理工作。如果我们在设计类的时候没有提供构造和析构函数,编译器会提供空实现的构造函数和析构函数。
构造函数:
作用:创建对象时为对象的成员属性赋值,由编译器自动调用;
语法:class name(){}
1.构造函数名称与类名相同;
2.没有返回值,也不写void;
3.构造函数可以有参数,可以发生重载;
4.程序在创建对象时会自动调用构造,而且只会调用一次。
析构函数:
作用:在对象销毁前系统自动调用,执行一些清理工作;
语法:~class name(){}
1.析构函数名称与类名相同,在类名前加~;
2.没有返回值,也不写void;
3.析构函数不可以有参数,所以不能发生重载;
4.程序在对象销毁时会自动调用析构函数,只会调用一次。
构造函数的分类和调用:
按照参数分为:有参构造和无参构造;
按照类型分为:普通构造和拷贝构造。
调用方式:括号法、显示法、隐式转换法。
下面是一个具体的例子:
class Student{
public:
Student(){
cout<<"无参构造函数"<<endl;
}
Student(string name){
m_name=name;
cout<<"有参构造函数"<<endl;
}
Student(const Student& student){
m_name=student.m_name;
cout<<"拷贝构造函数"<<endl;
}
~Student(){
cout<<"析构函数"<<endl;
}
public:
string m_name;
};
void test01(){
// 调用无参构造函数
Student student;
}
void test02(){
// 括号法
Student student1("jnny");
// 显示法,调用有参构造函数
Student student2=Student("lisa");
// 显示法,调用拷贝构造函数
Student student3=Student(student1);
string name="marry";
// 隐式转换法,调用有参构造函数
Student student4=name;
// 隐式转换法,调用拷贝构造函数
Student student5=student4;
}
构造函数调用规则:
1.如果用户定义有参构造函数,c++不再提供默认无参构造函数,但是会提供默认拷贝构造函数;
2.如果用户定义拷贝构造函数,c++不会在提供其他构造含数。
所以在设计一个类的时候,最好自己实现所有的构造函数。
深拷贝与浅拷贝:
浅拷贝指的是简单的赋值拷贝操作,深拷贝指的是在堆区重新申请空间,进行拷贝操作。如果构造函数中有在堆区申请空间的操作(也就是说属性在堆区开辟),则需要自己实现拷贝构造函数,并利用深拷贝在堆区重新创建新空间,否则会出现浅拷贝带来的重复释放堆区的问题。
下面是一个简单的例子:
class Student{
public:
Student(){
cout<<"无参构造函数"<<endl;
}
Student(string name,int age){
cout<<"有参构造函数"<<endl;
m_name=name;
m_age= new int(age);
}
Student(const Student& student){
cout<<"拷贝构造函数"<<endl;
m_name=student.m_name;
m_age=new int(*student.m_age);
}
~Student(){
cout<<"析构函数"<<endl;
if(m_age!=NULL){
delete m_age;
}
}
public:
string m_name;
int* m_age;
};
C++也可以利用初始化列表的方式来初始化属性,下面是一个小例子:
class Student{
public:
// 初始化列表方式
Student(string name,int age,string phone):m_name(name),m_age(age),m_phone(phone){}
public:
string m_name;
int m_age;
string m_phone;
};