C++学习笔记——构造函数与析构函数

在visual studio中可直接运行

#include <iostream>
#include <string>

using namespace std;

/******************************************************************
 1、构造函数和析构函数
     (1)构造函数   格式:类名() {}
	      a.没有返回值,也不写void
		  b.函数名与类名相同
		  c.可以有参数,可以发生重载
		  d.程序在调用对象的时候会自动调用构造函数,无需手动调用,而且只会调用一次
     (2)析构函数   格式:~类名() {}
		  a.没有返回值,也不写void
		  b.函数名与类名相同,在名称前加~
		  c.不可以有参数,不可以发生重载
		  d.程序在对象销毁前自动调用析构,无需手动调用,而且只会调用一次
 ******************************************************************/

 /******************************************************************
 2、构造函数的分类和调用
   (1)两种分类方式
		 a.按参数分类:有参构造函数(默认构造)和无参构造函数
		 b.按类型分类:普通构造函数和拷贝构造函数
   (2)三种调用方式
		 a.括号法
		 b.显示法
		 c.隐式转换法
 ******************************************************************/

 /******************************************************************
 3、拷贝构造函数调用时机
 (1)使用一个已经创建完毕的对象来初始化一个新对象
 (2)值传递的方式给函数参数传值
 (3)以值方式返回局部对象
 ******************************************************************/

 /******************************************************************
 4、构造函数的调用规则
 默认情况下,C++编译器至少给一个类添加3个函数
 (1)默认构造函数(无参,函数体为空)
 (2)默认析构函数(无参,函数体为空)
 (3)默认拷贝构造函数,对属性进行值拷贝

 构造函数的调用规则:
 (1)如果用户定义有参构造函数,C++不再提供默认无参构造,但是会提供默认拷贝构造
 (2)如果用户定义拷贝构造函数,C++不再提供其他构造函数
 ******************************************************************/

 /******************************************************************
 5、深拷贝与浅拷贝
	深拷贝:在堆区重新申请空间,进行拷贝操作
	浅拷贝:简单地赋值拷贝操作
 ******************************************************************/

 /******************************************************************
 6、初始化列表  用于初始化属性
 语法:构造函数():属性1(值1),属性2(值2)...{}
 ******************************************************************/

 /******************************************************************
 7、类对象作类成员
    class A{}
	class B{A a;}
	当类中成员是其他类对象时,我们称该成员为 对象成员
	构造顺序:先调用对象成员的构造,在调用本类构造
	析构顺序与构造相反
 ******************************************************************/

 /******************************************************************
 8、静态成员
    静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员
    静态成员分为:
    (1)静态成员变量
		a.所有对象共享同一份数据
		b.在编译阶段分配内存
		c.类内声明,类外初始化
	(2)静态成员函数
		a.所有对象共享同一个函数
		b.静态成员函数只能访问静态成员变量
 ******************************************************************/
class Car
{
public:
	Car() {}
	Car(int a, int b, int c) :m_A(a), m_B(b), m_C(c) 
	{
		cout << "调用Car的无参构造函数" << endl;
	}
	~Car()
	{
		cout << "调用Car的析构函数" << endl;
	}
	void printCar()
	{
		cout << "m_A=" << m_A << endl;
		cout << "m_B=" << m_B << endl;
		cout << "m_C=" << m_C << endl;
	}

	int m_A;
	int m_B;
	int m_C;
private:

};
class Person
{
public:
	//构造函数
	Person()
	{
		cout << "调用Person的无参构造函数" << endl;
	}
	Person(int a)
	{
		age = a;
		cout << "调用Person的有参构造函数" << endl;
	}
	Person(int a,int height)
	{
		age = a;
		m_Height = new int(height);//开辟在堆区,对象销毁前释放
		cout << "调用Person的两个入口参数的有参构造函数" << endl;
	}
	//自己实现拷贝构造函数,解决浅拷贝带来的问题
	Person(const Person &p)//const修饰,不能修改,
	{
		age = p.age;//将传入的人身上的所有属性,拷贝到我身上
		//m_Height = height;编译器默认拷贝函数实现的就是这行代码
		//深拷贝操作
		m_Height = new int(*p.m_Height);
		cout << "调用Person的拷贝构造函数" << endl;
	}
	~Person()
	{
		//析构代码,将堆区开辟数据做释放操作
		if (m_Height != NULL)
		{
			delete m_Height;
			m_Height = NULL;
		}
		cout << "调用Person的析构函数" << endl;
	}
	//静态成员函数
	static void func()
	{
		m_A = 100;//静态成员函数可以访问静态变量,该数据共享,只有一份
		//m_B = 200;//静态成员函数不可以访问非静态成员变量,无法区分到底是哪个对象的m_B
		cout << "调用static void func()" << endl;
	}
	int age;
	int * m_Height;
	static int m_A;
	int m_B;
	Car m_Pcar;//类对象成员
private:
	//静态成员函数也会有访问权限,类外不能访问
	static void func2()
	{
		cout << "调用static void func2()" << endl;
	}
};
int Person::m_A = 0;//静态成员变量类外初始化

/******************************************************************
2、构造函数的分类和调用
******************************************************************/
//构造和析构都是必须实现的,如果我们自己不提供,编译器会提供一个空实现的构造和析构
//调用
void test01()
{
	//1、括号法
	Person p1;//局部变量,存放在栈区,函数运行完释放(默认构造函数调用)
	Person p2(10);//有参构造函数调用
	Person p3(p2);//拷贝构造函数调用
	//注意事项1
	//调用默认构造函数,不加()
	//下面这行代码,编译器会认为是一个函数的声明,不会认为在创建对象
	//Person p1();
	cout << "p2的年龄:" << p2.age << endl;
	cout << "p3的年龄:" << p3.age << endl;

	//2、显示法
	Person p4 = Person(10);//有参构造
	Person p5 = Person(p4);//拷贝构造

	//Person(10);//匿名对象  特点:当前执行结束后,系统会立即收回匿名对象
	//cout << "1111" << endl;

	//注意事项2
	//不要利用拷贝构造函数初始化匿名对象,编译器会认为Person(p5) === Person p5;对象声明
	//Person(p5);

	//3、隐式转换法
	Person p6 = 10;//相当于写了 Person p4 = Person(10);有参构造
	Person p7 = p6;//拷贝构造
}
/******************************************************************
3、拷贝构造函数调用时机
******************************************************************/
//(1)使用一个已经创建完毕的对象来初始化一个新对象
void test02()
{
	Person p1(20);
	Person p2(p1);
	cout << "p2的年龄:" <<p2.age<< endl;
}
//(2)值传递的方式给函数参数传值
void doWork(Person p)
{

}
void test03()
{
	Person p;
	doWork(p);
}
//(3)以值方式返回局部对象
Person doWork2(void)
{
	Person p1;
	cout << (int *)&p1 << endl;
	return p1;
}
void test04()
{
	Person p = doWork2();
	cout << (int *)&p << endl;
	
}
/******************************************************************
5、深拷贝与浅拷贝
深拷贝:在堆区重新申请空间,进行拷贝操作
浅拷贝:简单地赋值拷贝操作
******************************************************************/
void test05()
{
	Person p1(18,160);
	cout << "p1的年龄:" << p1.age << " p1的身高:" << *p1.m_Height << endl;
	//利用编译器提供的拷贝构造函数,会做浅拷贝,  
	//浅拷贝带来的问题是堆区的内存重复释放
	//利用深拷贝进行解决
	Person p2(p1);
	cout << "p2的年龄:" << p2.age << " p2的身高:" << *p2.m_Height << endl;
}
/******************************************************************
8、静态成员
静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员
******************************************************************/
//有两种访问方式
void test06()
{
	//通过对象访问
	Person p;
	p.func();
	//通过类名访问
	Person::func();
}
int main()
{
	//test01();//调用构造函数方法
	//test02();//使用一个已经创建完毕的对象来初始化一个新对象
	//test03();//值传递的方式给函数参数传值
	//test04();//以值方式返回局部对象
	//test05();//深拷贝与浅拷贝
	//Car car(1,2,3);//列表初始化
	//car.printCar();
	//test06();//静态成员
	system("pause");
	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值