目录
对象的初始化和清理是两个非常重要的安全问题,一个对象或者变量没有初始时,对其使用后果是未知,同样的使用完一个变量,没有及时清理,也会造成一定的安全问题。c++为了给我们提供这种问题的解决方案,构造函数和析构函数,这两个函数将会被编译器自动调用,完成对象初始化和对象清理工作。
- #include
- #include
-
- using namespace std;
-
- class function
- {
- public:
- //构造函数 函数名和类名相同,没有返回值,不能有void,但可以有参数 可以重载
- function(int init_age,string init_name)
- {
- age = init_age;
- name = init_name;
- cout << "构造函数调用" << endl;
- }
- //析构函数 函数名是在类名前面加”~”组成,没有返回值,不能有void,不能有参数,不能重载
- ~function()
- {
- cout << "析构函数调用" << endl;
- }
- public:
- int age;
- string name;
- };
-
- void test()
- {
- function p1(10,"lucy");//构造函数在实例化对象时会创建,就是在内存开辟空间时会被调用
- //定义在栈区 test生命周期结束后会被销毁 在销毁之前自动调用析构函数
- }
-
- int main()
- {
- test();
- return 0;
- }
编译运行

按参数类型:分为无参构造函数和有参构造函数
按类型分类:普通构造函数和拷贝构造函数(复制构造函数)
拷贝构造:拷贝构造的调用时机:旧对象初始化新对象
其形参必须是引用,但并不限制为const,一般普遍的会加上const限制
如果自定义了一个拷贝构造 那么系统不再提供默认的拷贝构造
- #include
- #include
-
- using namespace std;
-
- class function
- {
- public:
- function()
- {
- cout << "无参构造函数" << endl;
- }
-
- function(int init_age,string init_name)
- {
- age = init_age;
- name = init_name;
- cout << "有参构造函数" << endl;
- }
- //拷贝构造的调用时机:旧对象初始化新对象
- //如果自定义了一个拷贝构造 那么系统不再提供默认的拷贝构造
- function(const function &p)//不能写function p 不能产生新对象
- {
- //拷贝构造做了简单的值拷贝
- age = p.age;
- name = p.name;
- cout << "拷贝构造" << endl;
- }
- ~function()
- {
- cout << "析构" << endl;
- }
-
- public:
- int age;
- string name;
- };
-
- void test01()
- {
- //如果人为提供了一个有参或无参构造 系统将不再提供默认的无参构造
- function p1;//调用无参构造时 不能加括号
- function p2(10,"lucy");
- function p3(p2);//调用系统提供的默认拷贝构造
- }
-
- void test02()
- {
- //匿名对象 没有名字 生命周期在当前行
- function (10,"tom");
- function ();
- function p1(20,"ben");
- //function p2(p); //匿名对象不能使用括号法调用拷贝函数
- }
- //显示法调用构造函数
- void test03()
- {
- function p1 = function (10,"tom");//显示法调用有参函数
- function p2 = function (p1); //显示法调用拷贝函数
- function p3 = function ();//显示法调用无参函数
-
- }
-
- int main()
- {
- test();
- return 0;
- }
默认情况下,c++编译器至少为我们写的类增加 3 个函数
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝构造函数,对类中非静态成员属性简单值拷贝
浅拷贝:同一类型的对象之间可以赋值,使得两个对象的成员变量的值相同,两个对象仍然是独立的两个对象,这种情况 被称为浅拷贝. 一般情况下,浅拷贝没有任何副作用,但是当类中有指针,并且指针指向动态分配的内存空间,析构函数做了动 态内存释放的处理,会导致内存问题。

深拷贝:当类中有指针,并且此指针有动态分配空间,析构函数做了释放处理,往往需要自定义拷贝构造函数,自行给指针动态分配空间。

- 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;
- }
class Person{public ://传统方式初始化Person(int a,int b,int c){mA = a;mB = b;mC = c;}//初始化列表方式初始化//先声明再根据声明的顺序定义初始化Person( int a, int b, int c):mA(a),mB(b),mC(c){}void PrintPerson(){cout << "mA:" << mA << endl;cout << "mB:" << mB << endl;cout << "mC:" << mC << endl;}private :int mA;int mB;int mC;};
类中有多个对象时,构造的顺序是先构造里面的对象,再构造外面的对象
类中有多个对象时,析构的顺序是先析构外面的对象,再析构外面的对象
- class Car{
- public:
- Car(){
- cout << "Car 默认构造函数!" << endl;
- mName = "大众汽车";
- }
- Car(string name){
- cout << "Car 带参数构造函数!" << endl;
- mName = name;
- }
- ~Car(){
- cout << "Car 析构函数!" << endl;
- }
- public:
- string mName;
- };
- //拖拉机
- class Tractor{
- public:
- Tractor(){
- cout << "Tractor 默认构造函数!" << endl;
- mName = "爬土坡专用拖拉机";
- }
- Tractor(string name){
- cout << "Tractor 带参数构造函数!" << endl;
- mName = name;
- }
- ~Tractor(){
- cout << "Tractor 析构函数!" << endl;
- }
- public:
- string mName;
- };
- //人类
- class Person{
- public:
- //类 mCar 不存在合适的构造函数
- Person(string name){
- mName = name;
- }
- //初始化列表可以指定调用构造函数
- Person(string carName, string tracName, string name) : mTractor(tracName),
- mCar(carName), mName(name){
- cout << "Person 构造函数!" << endl;
- }
- #endif
- void GoWorkByCar(){
- cout << mName << "开着" << mCar.mName << "去上班!" << endl;
- }
- void GoWorkByTractor(){
- cout << mName << "开着" << mTractor.mName << "去上班!" << endl;
- }
- ~Person(){
- cout << "Person 析构函数!" << endl;
- }
- private:
- string mName;
- Car mCar;
- Tractor mTractor;
- };
- void test(){
- //Person person("宝马", "东风拖拉机", "赵四");
- Person person("刘能");
- person.GoWorkByCar();
- person.GoWorkByTractor();
- }