C++学习第十三天(类和对象,对象的初始化和清理)

1.对象的初始化(构造函数)和清理(析构函数)
(1)构造函数:主要作用用于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用。
(2)析构函数:主要作用在于对对象销毁前系统自动调用,执行一些清理工作。
注意:对象的初始化和清理工作是编译器强制我们要做的事情,因此如果我们不提供这两个函数,编译器会提供编译器的这两个函数是空实现。

2.这两个函数的用法
(1)构造函数语法:类名(){}
a.构造函数没有返回值也不写void
b.函数名与类名相同
c.构造函数可以有参数,因此可以发生重载
d.程序在调用对象时会自动调用构造,无需手动调用,而且只调用一次
(2)析构函数语法:~类名(){}
a.析构函数没有返回值也不写void
b.函数名与类名相同,在函数名前加~
c.构造函数不可以有参数,因此不可以发生重载
d.程序在调用对象时会自动调用析构,无需手动调用,而且只调用一次

#include <iostream>
using namespace std;

class Person
{
public:
	//1.构造函数,进行初始化操作
	Person()
	{
		cout << "Person构造函数的调用" << endl;
	}
	//2.析构函数,进行清理操作
	~Person()
	{
		cout << "Person析构函数的调用" << endl;
	}
};

void test01()
{
	Person p;//在栈上的数据,test01执行完毕后,释放这个函数
}

int main()
{
	test01();
	Person p;//这里不会执行析构函数,只有在main函数执行完毕再回执行析构函数

	system("pause");
	return 0;
}

3.构造函数的分类及调用
(1)两种分类:按参数分为(有参构造和无参构造),按类型分类(普通构造和拷贝构造)
(2)调用方式:括号法、显示法、隐式转换法

#include<iostream>
using namespace std;

class Person
{
public:
	//无参(默认)构造函数
	Person()
	{
		cout << "Person无参构造函数的调用" << endl;
	}
	//有参构造函数
	Person(int a)
	{
		age = a;
		cout << "Person有参构造函数的调用" << endl;
	}
	//拷贝构造函数
	Person(const Person &p)
	{
		//将传入的这个人的所有属性,拷贝到当前对象函数
		age = p.age;
		cout << "Person拷贝构造函数的调用" << endl;
	}
	//析构函数
	~Person()
	{
		cout << "Person析构函数的调用" << endl;
	}
public:
	int age;
};
//调用
void test01()
{
	//括号法
	//注意事项1:调用默认构造函数时不要加(),加了括号编译器可能会将它默认为函数声明
	/*Person p1;
	Person p2(10);
	Person p3(p2);
	cout << "p2的年龄为:" << p2.age << endl;//10
	cout << "p3的年龄为:" << p3.age << endl;//10*/
	
	//显示法
	//Person p1;
	Person p2 = Person(10);//单独的Person(10)是一个匿名对象p2是给他命一个名
	cout << "aaaa" << endl;//这句话在有参构造函数调用后执行,然后在调用析构函数
	//Person p3 = Person(p2);
	//Person(10);//特点:当前行执行结束后,系统给会立即回收掉匿名对象
	//cout << "aaa" << endl;//这句话会在匿名对象被回收后才打印
	//注意事项2:不要利用拷贝构造函数,初始化匿名对象
	//Person(p2);//编译器会认为Person(p2) == Person p2,重复定义了
	
	//隐式转换法
	Person p4 = 10;//编译器默认为Person p4 = Person(10);
	Person p5 = p4;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

4.拷贝构造函数的调用时机
使用以下3种方式都会调用拷贝构造函数

#include <iostream>
using namespace std;

class Person
{
public :
	Person()
	{
		cout << "Person默认构造函数调用" << endl;

	}
	Person(int age)
	{
		cout << "Person有参构造函数调用" << endl;
		m_age = age;
	}
	Person(const Person &p)
	{
		cout << "Person拷贝构造函数调用" << endl;
		m_age = p.m_age;
	}
	~Person()
	{
		cout << "Person析构函数调用" << endl;
	}
public:
	int m_age;
};

//1.使用一个已经创建完毕的对象来初始化一个对象
void test01()
{
	Person p1(20);
	Person p2(p1);
	cout << "p2的年龄为:" << p2.m_age << endl;
}

//2.值传递的方式给函数参数传值
void dowork(Person p)
{
	
}
void test02()
{
	Person p;
	dowork(p);
}

//3.值传递返回局部对象
Person dowork2()
{
	Person p1;
	cout << (int *)&p1 << endl;
	return p1;
}
void test03()
{
	Person p = dowork2();
	cout << (int *)&p << endl;
}

int main()
{
	//test01();
	//test02();
	test03();
	system("pause");
	return 0;
}

5.构造函数调用规则
(1)在创建对象时C++编译器默认会提供三种构造函数
(2)如果用户定义有参构造函数,C++编译器不会在提供默认无参构造,但是会提供默认拷贝构造
(3)如果用户定义拷贝构造函数,c++编译器不会在提供其他构造函数(此时不能调用前两种构造函数)

6.浅拷贝:简单的赋值操作拷贝

7.深拷贝:在堆区重新申请空间,进行拷贝操作

#include <iostream>
using namespace std;

class Person
{
public:
	Person()
	{
		cout << "Person的默认构造函数调用" << endl;
	}
	Person(int age,int height)
	{
		m_height = new int(height);
		m_age = age;
		cout << "Person的有参构造函数调用" << endl;
	}
	//自己实现拷贝构造函数解决浅拷贝带来的问题
	Person(const Person &p)
	{
		cout << "Person 拷贝构造函数的调用" << endl;
		m_age = p.m_age;
		//m_height = p.m_height;编译器默认实现就是这行代码
		//深拷贝操作
		m_height = new int(*p.m_height);
	}
	~Person()
	{
		//析构函数,将堆区开辟数据做释放操作
		if (m_height != NULL)
		{
			delete m_height;//这里执行会出现错误,因为这个开辟的堆区会被连续释放
			m_height = NULL;//解决办法就是深拷贝
		}
		cout << "Person的析构函数调用" << endl;
	}
public:
	int m_age;
	int *m_height;
};

void test01()
{
	Person p1(18,180);
	cout << "p1的年龄为:" << p1.m_age << " p1的身高为:" << *p1.m_height << endl;//18
	Person p2(p1);
	cout << "p2的年龄为:" << p2.m_age << " p2的身高为:" << *p2.m_height << endl;//18编译器自动提供拷贝构造函数

}

int main()
{
	test01();
	system("pause");
	return 0;
}

8.用构造函数初始化列表

#include <iostream>
using namespace std;

//初始化列表
class Person
{
public:
	//传统初始化
	/*Person(int a, int b, int c)
	{
		m_a = a;
		m_b = b;
		m_c = c;
	}*/
	//列表初始化属性
	Person(int a , int b , int c) :m_a(a), m_b(b), m_c(c)
	{
		
	}
	int m_a;
	int m_b;
	int m_c;
};

void test01()
{
	/*Person p(10, 20, 30);
	cout << "m_a = " << p.m_a << endl;
	cout << "m_b = " << p.m_b << endl;
	cout << "m_c = " << p.m_c << endl;*/

	Person p(12,45,56);
	cout << "m_a = " << p.m_a << endl;
	cout << "m_b = " << p.m_b << endl;
	cout << "m_c = " << p.m_c << endl;
}

int main()
{
	test01();
	system("pause");
	return 0;
}

9.类对象作为类成员

#include <iostream>
#include <string>
using namespace std;

class Phone
{
public:
	Phone(string pname)
	{
		cout << "Phone的构造函数调用" << endl;//先构造
		m_pname = pname;
	}
	string m_pname;

};

class Person
{
public:
	Person(string name, string pname):m_name(name),m_phone(pname)
	{
		cout << "Person的构造函数调用" << endl;//后构造
	}
	//姓名
	string m_name;
	//手机
	Phone m_phone;

};

//当其他类作为本类成员,构造时先构造类对象,在构造自身,析构函数相反 
void test01()
{
	Person p("张三","苹果Max");
	cout << p.m_name << "拿着" << p.m_phone.m_pname<< "手机" << endl;
}

int main()
{
	test01();
	system("pause");
	return 0;
}

10.静态成员函数

#include <iostream>
using namespace std;

//静态成员函数
//所有对象共享同一个函数
//静态成员函数只能访问静态成员变量
class Person
{
public:
	static void func1()
	{
		m_a = 100;
		//m_b = 200;静态成员函数不可以访问非静态成员变量,因为无法区分到底是哪个对象的m_b属性
		cout << "static func1函数的调用" << endl;
	}
	static int m_a;//静态成员变量
	int b;//非静态成员变量

	//静态成员函数也是有访问权限的
private:
	static void func2()
	{
		cout << "static func1函数的调用" << endl;
	}
};

void test01()
{
	//1.通过对象访问
	Person p;
	p.func1();
	//2.通过类名访问
	Person::func1();
	//Person::func2();类外访问不到私有静态成员函数
}

int main()
{
	test01();
	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值