一、初步认识构造函数
1.什么是构造函数?
要了解构造函数就要先了解一下,类的6个默认成员函数,如下图:
构造函数:构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证 每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。
通俗一点来理解就是解决我们最烦的初始化问题。相当于在创建对象的时候自动调用或者编译自动生成来进行初始化。
2.构造函数特性
构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。
特征:
- 函数名和类相同。
- 没有返回值。
- 对象实例化时编译器自动调用对应的构造函数。
- 构造函数可以重载。
- 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
- 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。
如下示例:
2.1无参显式构造函数
#include<iostream>
using namespace std;
class A
{
public:
void Print()
{
cout << "Print()" << endl;
}
A(){
cout << "调用了A的构造函数" << endl;
}
private:
int _a;
};
int main()
{
A* a=nullptr;
a->Print();
A b;
return 0;
}
2.2有参显式构造函数
有参显式构造,可以把类中成员变量初始化成自己想要的值。
#include<iostream>
using namespace std;
class A
{
public:
void Print()
{
cout << _a << endl;
}
A(int a) {
cout << "调用了A的构造函数" << endl;
_a = a;
}
private:
int _a;
};
int main()
{
A b(100);
b.Print();
return 0;
}
其实涉及到传参,那么就会有全缺省和半缺省传参,下面举一个例子
#include<iostream>
using namespace std;
class A
{
public:
void Print()
{
cout << _a << endl;
cout << _b << endl;
}
A(int a,int b=100) {
cout << "调用了A的构造函数" << endl;
_a = a;
_b = b;
}
private:
int _a;
int _b;
};
int main()
{
A b(100);
b.Print();
return 0;
}
2.3隐式构造函数
如果想用隐式构造函数来初始化,那么一定不要显式写出构造函数,如果有显示构造函数首先优先执行构造函数。
#include<iostream>
using namespace std;
class A
{
public:
void Print()
{
cout << _a << endl;
}
private:
int _a;
};
class B
{
public:
void Print()
{
cout << _a << endl;
}
private:
int _a;
};
int main()
{
A b;
b.Print();
return 0;
}
我们发现我们不写构造函数,编译会自动生成构造函数,对内置类型(int/char/double/指针等)不做处理,也就是赋成随机值,对自定义类型( struct / class)会去调用他的默认构造。
2.4 C++11的补充补丁
C++11支持了在成员变量声明的时候给默认值,在生成默认构造函数的时候使用。
举一个例子如下:
#include<iostream>
using namespace std;
class A
{
public:
void Print()
{
cout << _a << endl;
cout << _b << endl;
}
//A(int a,int b=100) {
// cout << "调用了A的构造函数" << endl;
// _a = a;
// _b = b;
//}
private:
//默认生成构造函数的时候使用
int _a=100;
int _b=100;
};
int main()
{
A b;
b.Print();
return 0;
}
3.构造函数总结
- 构造函数一般情况下,有内置类型成员变量,就要考虑自己写构造函数,因为默认的构造函数对内置类型成员变量不处理(部分编译器处理),所以不能用编译器生成的,得自己显式写一个构造函数。
- 如果成员变量全部都是自定义类型成员,那么可以考虑让编译器自己生成。
二、初识析构函数
1.什么是析构函数?
析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。
通俗一点来说就是来进行扫尾,清除资源的占用,防止内存泄漏。(妈妈再也不用担心,内存泄漏咯)
2.析构函数的特性
特性:
- 析构函数名是在类名前面加上~。
- 无参数无返回值类型。
- 一个类只能有一个析构函数。若没有显示定义,系统会自动生成默认的析构函数。注意:析构函数不能重载。
- 对象生命周期结束时,C++编译系统会自动调用析构函数。
析构函数的例子
#include<iostream>
using namespace std;
class A
{
public:
void Print()
{
cout << _a << endl;
cout << _b << endl;
}
A(int a,int b=100) {
cout << "调用了A的构造函数" << endl;
_a = a;
_b = b;
}
~A()
{
cout << "调用了A的析构函数" << endl;
}
private:
//默认生成构造函数的时候使用
int _a=100;
int _b=100;
};
int main()
{
A b(100);
b.Print();
return 0;
}
由上图可以看出来,在对象生命周期快结束的时候,就自动调用了~A()