构造和析构
构造函数
定义
: C++中的类可以定义与类名相同的特殊成员函数,这种与类名相同的成员函数叫做构造函数。
“`c++
class 类名{
类名(形参){
构造体
}
}
* 比如:
class A
{
A(形参)
{
}
}
#define _CRT_SECURE_NO_WARNING
#include "stdafx.h"
using namespace std;
class Test
{
public:
Test(int x, int y) //Test类的构造函数,作用:在对象被创建时用来初始化对象的函数(函数可以被重载)
{
m_x = x;
m_y = y;
}
void Print_Point()
{
cout << "x = " << m_x << " ,y = " << m_y << endl;
}
private:
int m_x;
int m_y;
};
int main()
{
Test T1(1, 2);
T1.Print_Point();
return 0;
}
析构函数
~Test(); //析构函数没有形参,不能被重载
注意
:析构函数和构造函数都没有返回值。
什么时候用到析构函数呢?当对象T1是被在其他函数中使用的,那么执行完函数后T1被销毁前会触发析构函数。
如果自己不在类中写构造函数,那么编译器在编译的时候就会默认构造无参构造函数。(其实就是一个空函数Test();)
析构函数调用的顺序,跟构造相反,谁先构造的,谁后析构
拷贝构造函数
当我们需要用属于相同的类下的一个对象去初始化另一个对象时,需要用到拷贝函数。
比如在Test类中有如下一个拷贝函数,没有则系统默认:
Test(const Test &another) //注意这里的&anoher表示引用
{
m_x = another.m_x;
m_y = another.m_y;
}
则在主函数中写以下语句可以实现用一个已初始化的对象去未初始化的对象。
Test t1(1,2);
Test T1(t1); //可以通过t1给T1赋值,与Test T1 = t1;等价
深拷贝和浅拷贝
在main函数中要实现一个对象向另一个对象实现拷贝,往往用以下语句:
int main()
{
Teacher t1(1, "zhang3");
Teacher t2(t1);
return 0;
}
如果在类的定义中没有定义一个深拷贝函数,则编译器自动执行的将是浅拷贝函数,那么程序在执行时就会发生崩溃,原因如下:
* 编译器默认执行的浅拷贝函数:
Teacher(const Teacher &another)
{
m_id = another.m_id;
m_name = another.m_name; //将t1的成员拷贝给t2时,t2的指针*name将指向t1的*name所指向的堆区空间
}
那么当执行完浅拷贝后,将析构函数,即释放掉t2中的*name所指向的堆区空间,所以t1中*name所指向的空间也不存在了,那么当析构t1时,程序就会报错。所以要使用深拷贝函数:
Teacher(const Teacher &another) //实现深拷贝
{
m_name = (char*)malloc(sizeof(another.m_name));
strcpy(m_name, another.m_name);
m_id = another.m_id;
}
完整程序如下:
#include "stdafx.h"
using namespace std;
class Teacher
{
public:
Teacher(int id, char *name)
{
m_id = id;
m_name = (char*)malloc(sizeof(name));
strcpy(m_name, name);
}
void PrintT()
{
cout << "m_id = " << m_id << ", m_name = " << m_name << endl;
}
Teacher(const Teacher &another) //实现深拷贝
{
m_name = (char*)malloc(sizeof(another.m_name));
strcpy(m_name, another.m_name);
m_id = another.m_id;
}
~Teacher()
{
cout << "~Teacher()...." << endl;
}
private:
int m_id;
char *m_name;
};
int main()
{
Teacher t1(1, "zhang3");
t1.PrintT();
Teacher t2(t1);
t2.PrintT();
return 0;
}
编译结果如下:
构造函数的初始化列表
一个类的成员中有其他类的对象,那么要初始化这个对象,必须得把它写到初始化列表中。
class B
{
public:
B(A &a1,A &a2,int b):m_a1(a1),m_a2(a2)
{
m_b = b;
}
private:
int m_b;
A m_a1;
A m_a2;
}