C++对象的构造与析构用法

13 篇文章 0 订阅

构造函数和析构函数

初始化与清理

当大家买手机电脑的时候,都有一个初始化设置,也就是说这些产品当创建的时候都有一个基础值。随着时间推移,手机电脑用的越久文件越多,当我们不用的时候要清理,删除掉手机电脑中的数据,保护隐私。
C++中面对对象思想中这种方法,对事物抽象,比如当创建一个对象的时候,有的数据会有初始状态,当对象销毁的时候会销毁自己创建的数据。
从初始化与清理使两个重要操做,当初始化的时候,数据内容是未知的,如果没有清理,也会造成安全问题。所以引出构造函数与析构函数,这两个函数是编译器自动调用,完成初始化与清理。

构造函数语法

构造函数主要作用是为对象的成员属性赋值,构造函数由编译器自动调用,不用手动调用。
构造函数函数名和类名相同,没有返回值,不能加void,但可以有参数,可以重载

class A
{
public:
	//构造函数
	A()
	{
		c = 20;
	}
	//可以有参数
	A(int x)
	{
		C = X;
	}
private:
	int c;
};

析构函数语法

析构函数主要在对象销毁前系统自动调用,执行一些清理工作。
析构函数函数名和类名相同,在函数前面加’~"符号,不能有void,不能有参数,不能重载

class B
{
	//构造函数
	B()
	{
		cout << "构造函数" << endl;
	}
	//析构函数
	~B()
	{
		cout << "析构函数" << endl;
	}
};
class Person  //人的类
{
public:
	//使用构造函数申请内存,并进行初始话
	Person()
	{
		m_Name = (char*)malloc(sizeof("MyName"));
		strcpy(m_Name, "MyName");
		m_Tall = 185;
		m_Money = 10000;
	}
	//使用析构函数释放内存
	~Person()
	{
		if(m_Name != NULL)
		{
			free(m_Name);
			m_Name = NULL;
		}
	}
public:
	char* m_Name;
	int m_Tall;
	int m_Money;
};
void test()
{
	Person p;
	cout << p.m_Name << endl;
	cout << p.m_Tall << endl;
	cout << p.m_Money << endl;
}

构造函数的分类及调用

1.构造函数的分类:
无参构造函数,有参构造函数,拷贝构造函数
2.默认类默认提供了 默认构造函数,默认析构函数,默认拷贝构造函数,默认赋值函数

class test
{
public:
	test()
	{
		cout << "调用无参构造函数" << endl;
		age = 0;
	}
	test(int a)
	{
		age = a;
		cout << "调用有参构造函数" << endl;
	}
	t_printf()
	{
		cout << "age = " << age;
	}
	test(const test& t)//参数要写成引用
	{
		cout << "调用拷贝构造函数" << endl;
		age = t.age;
	}
	~test()
	{
		cout << "析构函数"
	}
private:
	int age;
};
int main
{
	//调用无参构造函数
	test t;
	t.t_printf();
	//无参构造错误的调用的方式
	test t1();
	t1.t_printf();

	//调用有参构造函数
	test t2(18);//常用这种方法
	t2.t_printf();
	//也可以使用这种方法调用
	//test t2 = 18;
	//test t2 = test(18);
	

	//调用拷贝构造函数,常用括号法调用拷贝构造函数
	test t3(t2);//常用这种方法
	t3.t_printf();
	//还可以使用=法调用
	//test t3 = t2; 
	//test t3 = test(t2);
	
	return 0;
}

拷贝构造函数中形参必须是引用
如果不使用引用会发生以下情况

class test
{
public:
	test()
	{
		cout << "调用无参构造函数" << endl;
	}
	test(int a)
	{
		cout << "调用有参构造函数" << endl;
	}
	test(const test t)
	{
		cout << "调用拷贝构造函数" << endl;
		age = t.age;
	}
	~test()
	{
		cout << "析构函数"
	}
private:
	int age;
};
int main()
{
	test t1;
	test t2(t1);
	//调用的时候会发生隐式转换
	/*test(const test t)
	{
		cout << "调用拷贝构造函数" << endl;
		age = t.age;
	}*/
	//const test t = t1;
	//const test t(m1);
	//const test t = t1;
	//进入死循环
	return 0;
}

匿名对象

匿名对象,就是没有名字的对象

class test
{
public:
	test()
	{
		cout << "构造函数" << endl;
	}
	test(int x)
	{
		a = x;
		cout << "有参构造函数" << endl;
	}
	~test()
	{
		cout << "析构函数" << endl;
	}
	int a;
};
void test01
{
	test(10);//匿名对象,没有名字
	//匿名对象的声明周期在当前行。
	test t1 = test(10); //如果匿名对象有对象名字来接,就不是匿名对象了。
	cout << "test01 end" << endl;
}

拷贝构造函数的调用时机

1.对象以值传递的方式传给函数参数

class test
{
public:
	test()
	{
		cout << "无参构造函数" << endl;
	}
	test(int a)
	{
		cout << "有参构造函数" << endl;
	}
	test(const test &t)
	{
		cout << "拷贝构造函数" << endl;
	}
	~test()
	{
		cout << "析构函数" << endl;
	}
};
//1.对象以值方式给函数参数
void func(test t)//test t=t1;
{

}

void test01()
{
	Maker t1;
	func(t1);

2.函数的局部对象以值的方式从函数返回,vs Debug(调试)模式下,会调用拷贝构造,vs Release(发行)模式下不会调用拷贝构造,qt也不调用

test func2()
{
	//局部对象
	test t;
	cout << "局部对象的地址:" << &t << endl;

	return t;
}

void test02()
{
	
	test t2 = func2();

	cout << "t2对象的地址:" << &t2 << endl;
}

Debug模式运行结果
在这里插入图片描述

Release模式运行结果
在这里插入图片描述

3.用一个对象初始化另一个对象

void test03()
{
	test t3;
	test t(t3);
}

构造函数调用规则

一、默认情况下C++编译器为我们加三个函数。
1.默认构造函数(无参,函数体为空)
2.默认拷贝构造函数(对类内非静态简单属性进行拷贝)
3.默认析构函数(无参,函数体为空)
二、如果用户定义了拷贝构造函数,编译器不会再提供任何默认的拷贝构造函数。

class T
{
public:
	//用户提供拷贝构造函数
	T(const T& t)
	{
		
	}
};
void test01()
{
	//T t;//错误
} 

三、如果用户定义了普通构造(非拷贝),编译器不会提供默认构造函数,会提供默认拷贝构造函数。

class T2
{
public:
	//用户提供有参构造函数
	T2(int x)
	{
		a = x;
	}
	int a;
};
void test02
{
	T2 t(10);//正确,调用有参构造
	//T2 t1;错误
	T2 t2(t);//调用默认构造函数
}

explicit关键字

C++提供了关键字explicit,禁止通过构造函数进行的隐式转换。声明为explic的构造函数的构造函数不能在隐式转换中使用。

explicit注意事项
1.explicit用于修饰构造函数,防止隐式转换
2.是针对单参数的构造函数(或除了第一个参数外其余参数都有默认值的多参构造函数)
class Mstring
{
public:
	explicit Mstring(int a)
	{
		cout << "Mstring(int a)" << endl;
	}
	/*针对单参数的构造函数,这样的使用也是正确的
	explicit Mstring(int a, int b = 2, int c = 3)
	{
		cout << "Mstring(int a, int b = 2, int c = 3)" << endl;
	}
	*/
	Mstring(const char *str)
	{
		cout << "Mstring(char* str)" << endl;
	}
};
void test()
{
	//Mstring s1 = 10; //产生错误不能进行隐式转换
	Mstring s2(20);//正确
	
	Mstring s3 = "abc";//正确
	Mstring s4("abc");//正确
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值