一、构造函数:函数名和类名相同的函数;
(1)意义:
他的作用是给成员变量进行赋值,也就是之前你的成员变量都是在主函数里边一个一个的初始化进行赋值,现在写个函数一次性把该赋的值都赋了。
(2)多种定义方式(多种传参方式):
构造函数的三种定义方法:
//1、直接定义对象(括号法)
//2、等号方法
//3、手动构造(函数名作为右值)
(3)调用时机
自动调用,也就是当遇到需要调用构造函数的时候,不需要你把函数名写过来到对应的代码位置,他会自己调用的;
#include <stdio.h>
class Test
{
public:
Test ()
{
m_a = 10;
m_b = 1000;
}
//有参构造函数;
Test(int a)
{
m_a = a;
printf("11111111有参构造函数调用\n");
}
Test (int a,int b)
{
m_a = a ;
m_b = b;
printf("222222222222个参数的构造函数\n");
}
void setAB(int a ,int b)
{
m_a = a ;
m_b = b;
}
void print()
{
printf("a = %d,b = %d\n",m_a,m_b);
}
private:
int m_a;
int m_b;
};
int main1()
{
//1、直接定义对象(括号法)
Test t1;
Test t2(10);
Test t3(10,20);
t2.print();
//2、等号方法
Test t4 = 10;
Test t5 = (10,20);
//Test t6 = "hello";
//3、手动构造
Test t6 = Test();
Test t7 = Test(10);
return 0;
}
二、析构函数
作用:用来在系统释放对象前做一些清理工作,如利用delete运算符释放临时分配的内存,清零某些内存单元等.当一个对象生存期结束时,系统会自动调用该对象所属类的析构函数;
简单地说就是释放内存资源,析构函数不被调用的话就会造成内存泄漏;
格式:
构造函数名之前加上符号~,例如构造函数Test(int a),析构函数就是~Test()。
调用时机:
自动调用;
三、拷贝构造(也是构造)
1、拷贝函数:test(const test &obj);
2、出现以下表达式的时候会调用拷贝构造(当然也是自动调用,不需要你在需要调用的时候写到相应的代码位置)
(1)Test t2 = t1; // 用对象 t1 去初始化t2
(2)Test t2(t0); // 用对象 t0 去初始化t2
(3)PrintObj(t0); // 做函数参数的时候
(4)t1 = test(); // 函数返回值返回对象
有没有发现,也就是需要用一个对象给另一个对象赋值的时候会自动调用拷贝构造!
四、总结构造函数的规则
构造函数的规则:
1)当类中没有定义任何一个构造函数时,c++编译器会提供默认无参构造函数和默认拷贝构造函数
2)当类中定义了拷贝构造函数时,c++编译器不会提供无参数构造函数
3)当类中定义了任意的非拷贝构造函数(即:当类中提供了有参构造函数或无参构造函数),c++编译器不会提供默认无参构造函数
4 )默认拷贝构造函数成员变量简单赋值
总结:只要你写了构造函数,那么你必须用。
构造析构阶段性总结
1)构造函数是C++中用于初始化对象状态的特殊函数
2)构造函数在对象创建时自动被调用
3)构造函数和普通成员函数都遵循重载规则
4)拷贝构造函数是对象正确初始化的重要保证
5)必要的时候,必须手工编写拷贝构造函数
五、深浅拷贝构造
深浅拷贝:
(1)、浅拷贝
默认复制构造函数可以完成对象的数据成员值简单的复制
对象的数据资源是由指针指示的堆时,默认复制构造函数仅作指针值复制
(2)、深拷贝
就是自己写拷贝函数;
延申:将拷贝函数私有化,只需要声明不需要实现也可以达到深拷贝的效果
private:
Test(const Test &t);
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 浅拷贝:在拷贝指针的时候只是拷贝了地址,不会进行空间的复制
class Test8_1
{
public:
Test8_1(int id, char *name)
{
m_id = id;
m_name = (char *)malloc(sizeof(char)*20);
strcpy (m_name, name);
}
~Test8_1()
{
if (m_name != NULL)
{
free (m_name);
m_name = NULL;
}
printf ("析构被调用**********\n");
}
void print()
{
printf ("id = %d, name = %s\n", m_id, m_name);
}
private:
int m_id;
// char m_name[20];
char *m_name;
};
// 深拷贝
class Test8_2
{
public:
Test8_2(int id, char *name)
{
m_id = id;
m_name = (char *)malloc(sizeof(char)*20);
strcpy (m_name, name);
}
// 自己写拷贝构造函数,避免浅拷贝
Test8_2(const Test8_2 &obj)
{
m_id = obj.m_id;
m_name = (char *)malloc(sizeof(char)*20);
strcpy (m_name, obj.m_name);
}
~Test8_2()
{
if (m_name != NULL)
{
free (m_name);
m_name = NULL;
}
printf ("析构被调用**********\n");
}
void print()
{
printf ("id = %d, name = %s\n", m_id, m_name);
}
private:
int m_id;
char *m_name;
};
class Test8_3
{
private:
// 将拷贝构造写成私有的函数,只需声明,不需要实现
Test8_3(const Test8_3 &ibj);
public:
Test8_3(int a)
{
m_a = a;
}
private:
int m_a;
};
int main8_3()
{
Test8_3 t(10);
// Test8_3 t1 = t;
return 0;
}
int main8_2()
{
Test8_2 t1(10, "wang");
t1.print();
// 调用自己写的拷贝构造函数,进行深拷贝
Test8_2 t2 = t1;
t2.print();
return 0;
}
int main8_1()
{
Test8_1 t1(10, "wang");
t1.print();
// 调用默认的拷贝构造函数
Test8_1 t2 = t1;
//t2.print();
return 0;
}