1.由来
类的数据成员不能在类的声明时候初始化,为了解决这个问题? 使用构造函数处理对对象的初始化。构造函数是一种特殊的成员函数,与其他函数不同,不需要用户调用它,而是创建对象的时候自动调用。析构函数是对象不再使用的时候,需要清理资源的时候调用。
2.基本语法
2.1构造函数
构造函数函数名和类名相同,没有返回值,不能有void,但可以有参数。
ClassName(){
}
2.2析构函数
析构函数函数名是在类名前面加”~”组成,没有返回值,不能有void,不能有参数,不能重载。
~ClassName(){
}
3.分类和调用
按参数类型:分为无参构造函数和有参构造函数
按类型分类:普通构造函数和拷贝构造函数(复制构造函数)
class Person{
public:
//默认构造函数
Person(){
cout << "默认构造函数!" << endl;
mAge = 0;
}
//有参构造函数
Person(int age){
cout << "有参构造函数!" << endl;
mAge = age;
}
//拷贝构造函数(复制构造函数) 使用另一个对象初始化本对象
Person(const Person& person){
cout << "拷贝构造函数!" << endl;
mAge = person.mAge;
}
//打印年龄
void PrintPerson(){
cout << "Age:" << mAge << endl;
}
private:
int mAge;
};
//1. 无参构造调用方式
void test01(){
//调用无参构造函数
Person person1;
person1.PrintPerson();
//无参构造函数错误调用方式
//Person person2();
//person2.PrintPerson();
}
//2. 调用有参构造函数
void test02(){
//第一种 括号法,最常用
Person person01(100);
person01.PrintPerson();
//调用拷贝构造函数
Person person02(person01);
person02.PrintPerson();
//第二种 匿名对象(显示调用构造函数)
Person(200); //匿名对象,没有名字的对象
Person person03 = Person(300);
person03.PrintPerson();
//注意: 使用匿名对象初始化判断调用哪一个构造函数,要看匿名对象的参数类型
Person person06(Person(400)); //等价于 Person person06 = Person(400);
person06.PrintPerson();
//第三种 =号法 隐式转换
Person person04 = 100; //Person person04 = Person(100)
person04.PrintPerson();
//调用拷贝构造
Person person05 = person04; //Person person05 = Person(person04)
person05.PrintPerson();
}
注意:不能调用拷贝构造函数去初始化匿名对象,也就是说以下代码不正确:
Person p1;
Person(p1) //这种调用是错误的,因为Person(p1)等价于Person p1,编译器认为这是个函数声明
4.拷贝构造函数的调用方式
4.1.用已经创建好的对象来初始化新的对象
Person p1;
p1.m_Age = 10;
Person p2(p1)
4.2.以值传递的方式给函数参数传值
void fun(Person p1) //Person p1 = Person(p)
{
}
void main()
{
Person p;
p.m_Age = 10;
fun(p);
}
4.3.以值方式返回局部对象
Person fun()
{
Person p1;
return p1;
}
void main()
{
Person p = fun();
}
注意:当环境设置为Release时,编译器会优化,例如:
Person fun() //原始代码
{
Person p1;
return p1;
}
void fun(Person & p1) //编译器优化完的代码
{
Person p1;
}
构造函数的调用规则
默认情况下,c++编译器至少为我们写的类增加3个函数
- 1.默认构造函数(无参,函数体为空)
- 2.默认析构函数(无参,函数体为空)
- 3.默认拷贝构造函数,对类中非静态成员属性简单值拷贝
如果用户定义拷贝构造函数,c++不会再提供任何默认构造函数
如果用户定义了普通构造(非拷贝),c++不在提供默认无参构造,但是会提供默认拷贝构造
5.浅拷贝和深拷贝
5.1浅拷贝
同一类型的对象之间可以赋值,使得两个对象的成员变量的值相同,两个对象仍然是独立的两个对象,这种情况被称为浅拷贝.
一般情况下,浅拷贝没有任何副作用,但是当类中有指针,并且指针指向动态分配的内存空间,析构函数做了动态内存释放的处理,会导致内存问题
5.2深拷贝
当类中有指针,并且此指针有动态分配空间,析构函数做了释放处理,往往需要自定义拷贝构造函数,自行给指针动态分配空间,深拷贝。
class Person{
public:
Person(char* name,int age){
pName = (char*)malloc(strlen(name) + 1);
strcpy(pName,name);
mAge = age;
}
//增加拷贝构造函数
Person(const Person& person){
pName = (char*)malloc(strlen(person.pName) + 1);
strcpy(pName, person.pName);
mAge = person.mAge;
}
~Person(){
if (pName != NULL){
free(pName);
}
}
private:
char* pName;
int mAge;
};
void test(){
Person p1("Edward",30);
//用对象p1初始化对象p2,调用c++提供的默认拷贝构造函数
Person p2 = p1;
}