对于一个变量或者对象如果没有初始化或者及时清理,造成的后果是未知的,会引发安全问题。所以C++提供了构造函数和析构函数来解决上面的问题,编译器会自动调用这两个函数,完成对对象的初始化和清理的工作。对象的初始化和清理是必须要执行的,若我们没有提供构造函数或者析构函数,编译器会自动提供这两个函数,只是都是空实现。
1、构造函数
构造函数主要作用于在创建对象时为对象的成员属性赋值,编译器会自动调用构造函数,不用手动的取调用。若没有提供构造函数,编译器会提供一个空实现的构造函数。例如:
//构造函数语法:类名{}
/*
* 注意:
* 1、构造函数没有返回值,void也不写
* 2、构造函数名称和类的名称一样
* 3、构造函数可以有参数,也可以发生重载
*/
class Person
{
public:
/*若没有提供构造函数,编译器会提供一个空实现的构造函数。无参构造函数,也叫默认构造函数*/
//Person(){}
//对成员属性进行赋值 构造函数
Person(string name,int age)
{
this->name = name;
this->age = age;
}
private:
string name;//姓名
int age;//年龄
};
在上面的例子中,在构造函数里面有参数,就叫做有参构造函数。
无参的构造函数又叫做默认构造函数,若类中没有显式的定义构造函数,编译器就会隐式的定义一个默认构造函数。对于默认构造函数来说,如果类内有初始值,就这个初始值来初始化成员,否则,就按照默认方式初始化成员(对于基本数据类型默认是未定义的值)。所以,建议通常要定义一个自己的构造函数,即使类中有没有初始化的成员,默认的构造函数就会对其进行默认初始化。如果我们自己定义的有其他构造函数,编译器就不会再自动的定义一个默认的构造函数。
除了上面说到的构造函数,还有拷贝构造函数。
拷贝构造函数是一种特殊的构造函数,它是利用一个已经存在的对象来初始化同类的一个新对象,拷贝构造函数的参数是一个对象的引用。声明和实现拷贝构造函数如下例子:
class Person
{
public:
//利用有参构造函数对成员属性进行赋值
Person(string name, int age)
{
this->name = name;
this->age = age;
}
/* 拷贝构造函数语法:类名(类名 &对象名)*/
//声明
Person(Person& p);
private:
string name;//姓名
int age;//年龄
};
//实现
Person::Person(Person& p)
{
name = p.name;
age = p.age;
}
如果没有自己定义拷贝构造函数,系统会在必要的时候自动生成一个隐含的拷贝构造函数,其功能是:把初始值的对象的每个数据成员的值复制到信建立的对象中。
构造函数的调用方法:
Person p;//默认构造函数调用
/*注意在调用默认构造函数的时候,不要加(),因为编译器会认为是一个函数的声明,不会认为是在创建对象*/
Person p1(10);//括号法调用有参构造函数
Person p2 = Person(10);//显示法调用有参构造函数
Person p3 = 10;//隐式法调用构造函数 相当于写了Person p3 = Person(10)
/*Person(10)是一种匿名对象,其特点是:执行结束后,系统会立即回收掉匿名对象
注意:不要利用拷贝构造函数初始化匿名对象 Person (p3),编译器会当成 Person p3 = Person p3 是一种对象声明*/
Person p3(p2);//括号法调用拷贝构造函数
Person p3 = Person(p2);//显示法调用拷贝构造函数
Person p3 = p2;//隐式法调用拷贝构造函数 相当于写了 Person p3 = Person(p1);
构造函数的调用规则:如果用户定义了有参构造函数,C++不会提供默认无参构造函数,但会提供默认拷贝构造;如果用户定义了拷贝构造函数,C++不会提供其他构造函数。
2、析构函数
主要作用于对象销毁前系统自动调用执行一些清理工作。例如:
class Person
{
public:
Person(int age)
{
//在堆区开辟空间存储年龄的大小
this->age = new int(age);
}
//析构函数
/*语法:~类名() {}
* 1、析构函数没有返回值,也不写void
* 2、析构函数名称与类名相同,前面加~
* 3、析构函数不可以有参数,不可以发生重载
*/
~Person()
{
//释放堆区开辟的空间
if (this->age != NULL)
{
delete this->age;
this->age = NULL;
}
}
private:
int* age;//年龄
};