C++ 构造函数

构造函数

分类

序号类型备注
1无参数构造函数默认构造函数
2带参数的构造函数
3普通构造函数
4拷贝构造

三种调用方法

序号方法
1括号法
2显示法
3隐式转换法

构造函数示例

class Person {
public:
	//无参(默认)构造函数
	Person() {
		cout << "无参构造函数!" << endl;
	}
	//有参构造函数
	Person(int a) {
		age = a;
		cout << "有参构造函数!" << endl;
	}
	//拷贝构造函数
	Person(const Person& p) {
		age = p.age;
		cout << "拷贝构造函数!" << endl;
	}
	//析构函数
	~Person() {
		cout << "析构函数!" << endl;
	}
public:
	int age;
};

构造函数用

//调用无参构造函数
void test01() {
	Person p; //调用无参构造函数
}

//调用有参的构造函数
void test02() {

	//2.1  括号法,常用, QString str("This is a demo")
	Person p1(10);
	//注意1:调用无参构造函数不能加括号,如果加了编译器认为这是一个函数声明
	//Person p2();

	//2.2 显式法
	Person p2 = Person(10); 
	Person p3 = Person(p2);
	//Person(10)单独写就是匿名对象  当前行结束之后,马上析构

	//2.3 隐式转换法
	Person p4 = 10; // Person p4 = Person(10); 
	Person p5 = p4; // Person p5 = Person(p4); 

	//注意2:不能利用 拷贝构造函数 初始化匿名对象 编译器认为是对象声明
	//Person p5(p4);
}

拷贝构造的使用场景

序号场景备注
1使用一个已经创建完毕的对象来初始化一个新对象
2值传递的方式给函数传值
3以值方式返回局部对象

场景1

  • 使用一个已经创建完毕的对象来初始化一个新对象
void test_scene_1(void)
{
	Person man(18);			//创建一个对象
	Person new_man(man);    //调用拷贝构造函数
	Person another_man = man; //拷贝构造
}

场景 2

  • 值传递的方式给函数参数传值
void dowork(Person p1)
{
	cout<<p.age<<endl;
}

void test_scene_2()
{
	Person p;		//无参构造函数
	dowork(p);		
}

场景3

  • 以值方式返回局部对象
Person dowork2()
{
	Person p1;					//无参构造函数
	cout << (int*)&p1 <<endl;   //输出地址:010FF6C0
	return p1;   				//利用p1创建一个新的对象,返回给外部,并不是返回上面的p1,因为栈变量在函数退出时,就释放空间了。
}

void test_scene_3(void)
{
	Person p = dowork2();		
	cout << (int *)&p << endl;	//输出地址:010FF7B8
								//退出该函数时调用析构函数
}

构造函数调用规则

当创建一个类时,C++编译器至少给一个类添加3个函数

序号函数说明
1默认构造函数无参数,函数体为空
2默认析构函数无参数,函数体为空
3默认拷贝构造函数对属性值进行拷贝

调用规则

  • 如果用户定义有参构造函数,C++不再提供默认无参构造,但是会提供默认拷贝构造
  • 如果用户定义拷贝构造函数,C++不会再提供其他构造函数

深浅拷贝

  1. 浅拷贝: 简单的赋值拷贝操作
  2. 深拷贝: 在堆区重新申请空间,进行拷贝操作
class Person {
public:
	Person() {
		cout << "无参构造函数!" << endl;
		m_age = 0;
	}
	Person(int age, int height) {
		cout << "有参构造函数!" << endl;
		m_age = age;
		m_height = new int(height);
	}
	Person(const Person& p) {
		cout << "拷贝构造函数!" << endl;
		m_age = p.m_age;
		//m_height = p.m_height; //如果让编译器自动生成拷贝构造函数,则这里是这样子的。但是问题就出在析构的地方
		cout << "为m_height 重新开辟空间" << endl;
		m_height = new int(*p.m_height);
	}
	//析构函数在释放内存之前调用
	~Person() {
		cout << "析构函数!" << endl;
		if (m_height!=NULL)
		{
			cout << "释放m_height指向的堆空间内存" << endl;
			delete m_height;
			m_height = NULL;

		}
	}
public:
	int		m_age;				//成员变量
	int*	m_height;			//指针类型的成员变量
};


static void test_deepcopy_construct(void)
{
	Person p1(18, 180);
	Person p2(p1);

	cout << "p1的年龄: " << p1.m_age << " 身高: " << *p1.m_height << endl;
	cout << "p2的年龄: " << p2.m_age << " 身高: " << *p2.m_height << endl;
}

程序输出

有参构造函数!
拷贝构造函数!
为m_height 重新开辟空间
p1的年龄: 18 身高: 180
p2的年龄: 18 身高: 180
析构函数!
释放m_height指向的堆空间内存
析构函数!
释放m_height指向的堆空间内存

深拷贝的注意

如果属性有在堆区开辟的,一定要自己实现拷贝构造函数,防止浅拷贝带来的在析构时,释放同一片内存的问题。

深拷贝注意事项

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值