C++学习笔记(十二)

在完成对C语言的学习后,我最近开始了对C++和Java的学习,目前跟着视频学习了一些语法,也跟着敲了一些代码,有了一定的掌握程度。现在将跟着视频做的笔记进行整理。本篇博客是整理C++知识点的第十二篇博客。

本篇博客介绍了C++的构造函数。

本系列博客所有C++代码都在Visual Studio 2022环境下编译运行。程序为64位。

目录

构造函数

拷贝构造函数的调用时机

构造函数调用规则

深拷贝与浅拷贝

初始化列表

类对象作为类成员


构造函数

这一部分接着上一篇对构造函数的初步介绍。

拷贝构造函数的调用时机

C++中,调用拷贝构造函数的时机通常有这三种情况:

使用一个已经创建的对象初始化一个新对象。

用值传递给函数参数传参。

以值的方式返回局部对象。

#include<iostream>
using namespace std;
class test {
public:
	int age;
	test() {
		cout << "This is A" << endl;
	}
	test(const int num) {
		age = num;
		cout << "This is B" << endl;
		cout << "Age = " << age << endl;
	}

	test(const test& temp) {
		age = temp.age;
		cout << "This is C" << endl;
		cout << "Age = " << age << endl;
	}
};

int main(void)
{
	test test1;
	test test2(10);
	test test3(test2);
	return 0;
}

程序中用已经创建的test2初始化一个新的对象test3。

程序的输出是:

This is A
This is B
Age = 10
This is C
Age = 10

#include<iostream>
using namespace std;
class test {
public:
	int age;
	test() {
		cout << "This is A" << endl;
	}
	test(const int num) {
		age = num;
		cout << "This is B" << endl;
		cout << "Age = " << age << endl;
	}
	test(const test& temp) {
		age = temp.age;
		cout << "This is C" << endl;
		cout << "Age = " << age << endl;
	}
};
void testfunc(test temp);

int main(void)
{
	test test1(10);
	testfunc(test1);
	return 0;
}

void testfunc(test temp)
{
	return;
}

程序创建了一个test1对象,随后将这个对象作为参数以值传递的方式传递给testfunc函数。testfunc函数只接受这个参数,什么也不执行。因为值传递需要拷贝,所以会执行拷贝构造函数。

程序的输出是:

This is B
Age = 10
This is C
Age = 10

#include<iostream>
using namespace std;
class test {
public:
	int age;
	test() {
		cout << "This is A" << endl;
	}
	test(const int num) {
		age = num;
		cout << "This is B" << endl;
		cout << "Age = " << age << endl;
	}

	test(const test& temp) {
		age = temp.age;
		cout << "This is C" << endl;
		cout << "Age = " << age << endl;
	}
};
test testfunc(void);
int main(void)
{
	test test2 = testfunc();
	return 0;
}

test testfunc(void)
{
	test test1(10);
	return test1;
}

程序进入main函数后,先执行testfunc函数,testfunc函数创建了一个对象,并将该对象返回main函数,main函数接收后返回。由于返回值也是拷贝,会调用拷贝构造函数。

程序的输出是:

This is B
Age = 10
This is C
Age = 10

构造函数调用规则

默认情况下,C++编译器会给一个类添加一个默认构造函数,此构造函数无参,函数体为空。还会添加一个默认析构函数,函数体为空。还会添加一个默认拷贝构造函数,对属性进行值拷贝。

如果已经自定义有参构造函数,那么编译器不再提供默认无参构造函数,但是会提供默认拷贝构造。如果自定义拷贝构造函数,那么编译器不会提供其他构造函数。

深拷贝与浅拷贝

浅拷贝就是简单的赋值拷贝操作,深拷贝会在堆区重新申请空间,进行拷贝。

编译器默认浅拷贝,这样在释放空间时造成重复释放,会导致程序崩溃。如果一个类中有堆区的数据,并且涉及到拷贝,要自己提供拷贝构造函数进行深拷贝。

#include<iostream>
using namespace std;
class test {
public:
	int age;
	int* height;
	test() {
		cout << "This is A" << endl;
	}
	test(const int numage, const int numheight) {
		age = numage;
		height = new int(numheight);
		cout << "This is B" << endl;
		cout << "Age = " << age << endl;
		cout << "Height = " << *height << endl;
	}

	test(const test& temp) {
		age = temp.age;
		height = new int(*temp.height);
		cout << "This is C" << endl;
		cout << "Age = " << age << endl;
		cout << "Height = " << *height << endl;
	}
	~test() {
		delete height;
		cout << "This is D" << endl;
	}
};

int main(void)
{
	test test1(20, 170);
	test test2(test1);
	return 0;
}

test类提供只输出This is A的无参构造函数。同时提供一个有参构造函数,对age和height进行赋值,age存储在栈区,height存储在堆区,进行了内存开辟。同时输出This is B和成员变量信息。同时提供拷贝构造函数,对height进行了深拷贝,同时输出This is C和成员变量信息。test类的析构函数将height销毁,同时输出This is D。

main函数用有参构造函数和拷贝构造函数进行初始化。程序的输出是:

This is B
Age = 20
Height = 170
This is C
Age = 20
Height = 170
This is D
This is D

初始化列表

C++提供了初始化列表,用来初始化属性。语法是:

构造函数():属性1(值1),属性2(值2),属性3(值3)...{...}

#include<iostream>
using namespace std;
class test {
public:
	int A;
	int B;
	int C;
	test() :A(10), B(15), C(20){}
	test(int a,int b,int c) :A(10), B(15), C(20)
	{
		A = a;
		B = b;
		C = c;
	}

	void show() {
		cout << "A = " << A << endl;
		cout << "B = " << B << endl;
		cout << "C = " << C << endl;
	}
};
int main(void)
{
	test atest;
	atest.show();
	return 0;
}

程序创建了test类,test类有成员A,B,C,构造函数中默认初始化值为10,15,20。程序创建了一个类对象,并调用了无参构造函数。程序的输出是:

A = 10
B = 15
C = 20

如果用构造函数,传入三个0作为参数,程序的输出是:

A = 0
B = 0
C = 0

类对象作为类成员

一个类的成员可以是另一个类的一个对象。

当有其他类的对象作为本类成员时,构造时先构造类对象,后构造自身,析构时相反。

#include<iostream>
#include<string>
using namespace std;
class Phone {
public:
	string brand;
	Phone(void) {
		cout << "A" << endl;
	}
	~Phone(void) {
		cout << "Z" << endl;
	}
};

class Person {
public:
	string name;
	Phone phone;
	Person(string tempname, string tempbrand){
		cout << "a" << endl;
		name = tempname;
		phone.brand = tempbrand;
	}

	void show() {
		cout << "The name is " << name << endl;
		cout << "The phone is " << phone.brand << endl;
	}
	~Person() {
		cout << "z" << endl;
	}
};
int main(void)
{
	Person people("Allen", "Apple");
	people.show();
	return 0;
}

程序提供了Phone类,有一个成员变量brand,构造函数输出A,析构函数输出Z。程序还有Person类,有一个成员变量是字符串name,另一个成员变量是Phone类对象phone。Person类的带参构造函数输出a,同时对成员变量进行赋值。析构函数输出z,show函数输出成员变量信息。main函数中实例化Person类对象并执行此对象的show函数。

程序的输出是:

A
a
The name is Allen
The phone is Apple
z
Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值