C++类和对象(2):构造函数和析构函数、构造函数初始化列表

注意:

  • 1.类的属性可以是另一个类;(定义类时注意)
  • 2.实现成员函数中:要使用“::”作用域符号,这样才能定义/实现成员函数,否则会报错;
  • 3.在实现函数.cpp和main.cpp中都要包含.h头文件,如果一个头文件中使用另一个类,也需要引用对应的头文件

对象的初始化和清理

构造函数和析构函数

在这里插入图片描述
在这里插入图片描述

C++提供了构造函数和析构函数完成对象初始化和清理工作;

  • 对象的初始化和清理工作是编译器强制要我们做的事情,因此如果我们不提供构造和析构函数,编译器会提供;但是**编译器提供的构造函数和析构函数时空实现的**——所以需要我们自己编写;
  • 构造函数主要作用在创建对象时为对象的成员赋值,构造函数有编译器自动调用,无需手动调用;
  • 析构函数主要作用在于对象销毁前系统自动调用,执行一些清理工作;
    在这里插入图片描述
    在这里插入图片描述
    - 构造函数和析构函数异同点:
    - 相同点:
    1.都没有返回值,也不用写void;
    2.函数名称都与类名一致(析构函数在名称钱加上符号-)
    3.都无需手动调用,由系统自动调用
    - 不同点:
    1.构造函数可以有参数,所以可以重载;而析构函数不可以有参数,因此不可以发生重载;
    2.构造函数在创建对象时自动调用;而析构函数在对象销毁前自动调用;
    因为要在外界调用构造函数和析构函数,所以给构造函数和析构函数的访问权限为public;
class Person
{
public:
	Person();
	~Person();

private:

};

Person::Person()
{
	cout << "自动调用构造函数"<<endl;
}

Person::~Person()
{
	cout << "自动调用析构函数"<<endl;
}

void test(){
	//在函数中创建的变量是存在栈区的,所以在函数结束后会自动清理
	Person p1;
}
int main() {
	test();
	//只会调用构造函数
	Person p2;	
	system("pause");	//暂停一下以便查看
	return 0;	//标准的返回退出
 }

在这里插入图片描述

构造函数的分类及调用:

  • 两种分类方式:
    1.按参数分为:有参构造和无参构造;
    2.按类型分为:普通构造和拷贝构造;
class Person {
public:
	int age;
	Person() {
		cout << "调用了无参构造函数"<<endl;
	}
	Person(int Age) {
		age = Age;
		cout << "调用了有参构造函数"<<endl;
	}
	Person(const Person &p) {
		//将传入的人身上的所有属性,拷贝到新创建的对象中;
		age = p.age;
		cout << "调用了拷贝构造函数"<<endl;
	}
};
int main() {
	Person p1;
	Person p2(10);
	Person p3(p2);
	cout <<"p3的年龄为:"<< p3.age << endl;
	system("pause");	//暂停一下以便查看
	return 0;	//标准的返回退出
 }

拷贝构造函数注意:参数为const Person &p——要用const进行锁定,防止对原对象进行修改;

  • 三种调用方式:
    1.括号法;
括号法:
	Person p1;
	Person p2(10);
	Person p3(p2);

在这里插入图片描述
注意事项:调用默认构造函数时,不要加()
因为Person p1( )代码,编译器会认为是一个函数的声明,不会认为在创建对象;
跟函数声明类似:void func();

2.显示法

显示法:
	Person p1;
	Person p2 = Person(10);	//有参构造
	Person p3 = Person(p2);  //拷贝构造
	cout <<"p3的年龄为:"<< p3.age << endl;

注意:

Person(10)——相当于一个匿名对象,然后给他取名字;
特点:当前行执行结束后,系统会立即回收掉匿名对象;

不要利用拷贝函数初始化匿名对象;编译器会认为Person(p3)等价于Person p3;相当于对象声明

3.隐式转换法(了解)

	Person  p4 = 10;	相当于写了Person p4 = Person(10);——有参构造函数
	Person  p5 = p4;	拷贝构造

拷贝构造函数调用时机:

C++中拷贝构造函数调用时机通常有三种情况:
  • 使用一个已经创建完毕的对象来初始化一个新对象;
	Person p1(p3);————这时会调用拷贝构造函数
  • 值传递的方式给函数参数传值;
	void  Copy(Person p){  } ————这时也会调用拷贝构造函数;
  • 以值方式返回局部对象;
	Person Copy(){
		Person p;
		return p;
	}

构造函数调用规则:

在这里插入图片描述
注意:默认拷贝构造函数是对所有属性值都会进行拷贝;

	Person p;
	p.age = 18;
	p.id = 123;
	Person p1(p);
	cout << "p1的年龄为:" << p1.age << endl;
	cout << "p1的学号为:" << p1.id << endl;

在这里插入图片描述
注意:

  • 当我们写了有参构造函数时,C++将不提供无参构造函数,但会提供默认拷贝构造函数;
  • 而当我们定义了拷贝构造函数,C++则不会再提供其他构造函数;

深拷贝与浅拷贝:

深浅拷贝是面试经典问题,也是常见的一个坑;

  • 浅拷贝:简单的赋值拷贝操作;

  • 深拷贝:在堆区重新申请空间,进行拷贝操作;
    在这里插入图片描述
    在这里插入图片描述

  • 深拷贝:解决当出现在堆区开辟内存,然后在析构函数中释放内存时出现的问题;

初始化列表

在这里插入图片描述

	Person(int x_age,int x_id) {
		age = x_age;
		id = x_id;
	}
	Person p(18,10);
	Person(int x_age, int x_id) :age(x_age), id(x_id) {

	}
	Person p(18,10);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值