文章目录
- 默认成员函数
- 构造函数
- 默认构造函数
- 析构函数
- 不同生命周期的构造、析构函数的执行顺序
默认成员函数
在c++中,每个类里面都有六个默认成员函数。即便这个类什么都没有,也就是空类,也会有这六个成员函数。这些函数的存在极大的简化了代码的实现,并且一定程度上提高了代码的安全性。
构造函数
构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。
特点:
- 函数名与类名相同。
- 无返回值。
- 对象实例化时编译器自动调用对应的构造函数。
- 构造函数可以重载。
class A()
{
private:int a;double b;
public:A(int x=0){cout<<"A()"<<x<<endl;}
}
int main()
{A a1;A a1(10);return 0;
}
上述代码的运行结果告诉我们,当对象实例化的时候就会自动运行构造函数。
要注意的是,实例化时不可以如下:
int main()
{A a1;A a2(10);A a3();return 0;
}
这个运行结果还是和上面的代码运行结果相同,这时因为编译器将A a3();识别成了函数声明。
默认构造函数
对于可以无参的构造函数统称为默认构造函数,包括全缺省构造函数,无参构造函数、编译器默认生成的构造函数。(日常中建议使用全缺省的构造函数)
对于编译器默认生成的构造函数会根据类的属性的不同进行不同的处理:
- 内置类型(基本类型):声明时赋给默认值,如果没有默认值就不做处理。
- 自定义类型:调用其自身的构造函数。
class B
{
private:int x;
public:B(){cout << "B()" << endl;x = 0;}
};
class A
{
private:int a=10;//默认值double b;B bb;
public:void Print(){cout << a << ' ' << b << endl;}
};
int main()
{A a1;a1.Print();return 0;
}
如上,A中的int a默认值为10所以初始化为10,b则不做处理为随机值。B bb为自定义类型,执行了B的构造函数。
析构函数
析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。
特点:
- 析构函数名是在类名前加上字符 ~。
- 无参数无返回值类型。
- 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
- 对象生命周期结束时,C++编译系统系统自动调用析构函数。
析构函数的存在能能够帮我们在函数生命周期结束时自动释放动态开辟的空间,有效地避免了空间泄露。
此外,若没有自行定义类的析构函数。那么编译器就会生成默认的析构函数,其对不同成员变量的处理参照默认构造函数对不同成员变量的处理。
不同生命周期的构造、析构函数的执行顺序
class A
{
public:A(){cout << "A()" << endl;}~A(){cout<< "~A()" << endl;}
};
class B
{
public:B(){cout << "B()" << endl;}~B(){cout << "~B()" << endl;}
};
class C
{
public:C(){cout << "C()" << endl;}~C(){cout << "~C()" << endl;}
};
class D
{
public:D(){cout << "D()" << endl;}~D(){cout << "~D()" << endl;}
};
int main()
{B b1;static C c1;D d1;return 0;
}
A a1;
根据上述代码的运行结果可知:
- 构造函数的执行顺序:首先是全局变量的构造函数,然后是主函数里的局部变量构造函数从上往下依次进行。
- 析构函数的执行顺序:先执行主函数里的局部变量的析构函数从下往上依次进行,然后执行静态区的析构函数,最后才是全局变量的析构函数。