一、构造函数:
- 用来对新建的对象进行初始化操作。
- 名称和类名一样
- 不能有返回值
- 参数通常用来对成员变量进行初始化。
- 可以用pulic、public、private 等访问控制符修饰。
- 可以进行重载,但 重载时注意默认参数的使用,不要引起二义性。
二、析构函数
- 用来释放对象所占的内存空间,特别是释放内部对象所占用的空间。通常和构造函数的写法对应,加入在构造函数进行了new 或 malloc ,就需要了析构函数中进行delete 或free。
- 名称为~类名
- 无参数
- 无返回值
- 可以用public、public、private 修饰
- 不能重载,只能有一个
在使用new 生成对象时,会自动根据参数调用合适的构造函数,在delete对象时,会自动调用析构函数进行清理操作。在类定义时,如果没有显示的给出构造、析构函数,编译器会自动添加默认的构造、析构函数。
构造函数与析构函数的调用:在生成对象时调用构造函数,对象消亡时调用析构函数.
1、若构造函数和析构函数为私有的,则只能在类中的方法里调用构造函数生成对象(这种用法可以限制生成对象的个数,比如,单例模式),在类内部调用析构函数。所以在类外面就不能使用 new 和delete 运算符来创建对象和释放对象。一般只会在单例模式,工厂模式等特殊情况下会这样使用,私有的构造函数+ 公有的析构函数。
2、若构造函数为公有的,则可以在任意位置生成该类的对象。
析构函数为公有的,则在运行delete或离开对象的作用域时调用析构函数
3、在主函数中显式调用构造函数,或在类的方法中返回一个构造函数对象。生成一个临时的对象,在执行完该函数所在的语句后释放该临时对象。一般不建议这样使用。
比如:
static TestClass TestClass::newInstance()
{
returnTestClass();
}
Main 函数中:
TestClass tt = TestClass::newInstance();//ok
TestClass *tt1 = &TestClass::newInstance(); //error
虽然编译没有出错,但运行的时候就可能发生不可预知的错误了。
返回编代码如下
00166849 lea eax,[ebp-108h]
0016684F push eax
00166850 call TestClass::newInstance (0161127h)
00166855 add esp,4
00166858 mov dword ptr [ebp-128h],eax
0016685E mov ecx,dword ptr [ebp-128h]
00166864 mov dword ptr [tt1],ecx
00166867 lea ecx,[ebp-108h]
0016686D call TestClass::~TestClass (0161253h)
4、构造函数中对成员的初始化方式:
class A
{
public:
int a;
float b;
char c;
}
那么A的构造函数中有两种方式初始化a,b,c
第一种:
A::A(intx,float y,char z)
{
a= x;
b= y;
c= z;
}
这是常规的初始化方式,我们可以以这种方式来初始化任何变量。
第二种:
A::A(intx, float y, char z):a(x), b(y), c(z)
{
}
这里,我们在构造函数头的地方,紧接着进行变量的初始化(包括调用基类的构造函数)。
两种方式的比较,第一种方式在定义对象时,先分配一块存储空间,然后初始化为0,然后按照构造函数的内容进行初始化。第二种方式在定义对象时,在分配空间之后,就使用内存复制函数进行初始化,然后再用构造函数中的内容对其他的成员进行初始化。
所以我们一般推荐使用第二种方式对基本类型成员初始化,对于其他复杂的结构成员用第一种方式初始化。