2024年最新C++笔记4(9),2024C C++开发面试题及答案

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

//1. 使用一个已经创建完毕的对象来初始化一个新对象

void test01() {

Person man(100); //p对象已经创建完毕

Person newman(man); //调用拷贝构造函数

Person newman2 = man; //拷贝构造 隐式转换法



//Person newman3;

//newman3 = man; //不是调用拷贝构造函数,赋值操作

}

//2. 值传递的方式给函数参数传值

//相当于Person p1 = p;

void doWork(Person p1) {}

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;

}




#### []( )4.2.4 构造函数调用规则



默认情况下,c++编译器至少给一个类添加3个函数(编译器自动添加)



1.默认构造函数(无参,函数体为空)



2.默认析构函数(无参,函数体为空)



3.默认拷贝构造函数,对属性进行值拷贝



构造函数调用规则如下:



*   如果用户定义有参构造函数,c++不在提供默认无参构造,但是会提供默认拷贝构造

    

*   如果用户定义拷贝构造函数,c++不会再提供其他构造函数

    



**注意(作者解读):如果自己写了更高级的构造函数,则编译器不会提供低级的构造函数,但会提供更高级的构造函数**



**示例:**



class Person {

public:

//无参(默认)构造函数

Person() {

	cout << "无参构造函数!" << endl;

}

//有参构造函数

Person(int a) {

	age = a;

	cout << "有参构造函数!" << endl;

}

//拷贝构造函数

Person(const Person& p) {

	age = p.age;

	cout << "拷贝构造函数!" << endl;

}

//析构函数

~Person() {

	cout << "析构函数!" << endl;

}

public:

int age;

};

void test01()

{

Person p1(18);

//如果不写拷贝构造,编译器会自动添加拷贝构造,并且做浅拷贝操作

Person p2(p1);



cout << "p2的年龄为: " << p2.age << endl;

}

void test02()

{

//如果用户提供有参构造,编译器不会提供默认构造,会提供拷贝构造

Person p1; //此时如果用户自己没有提供默认构造,会出错

Person p2(10); //用户提供的有参

Person p3(p2); //此时如果用户没有提供拷贝构造,编译器会提供



//如果用户提供拷贝构造,编译器不会提供其他构造函数

Person p4; //此时如果用户自己没有提供默认构造,会出错

Person p5(10); //此时如果用户自己没有提供有参,会出错

Person p6(p5); //用户自己提供拷贝构造

}

int main() {

test01();

//test02();

system("pause");



return 0;

}




#### []( )4.2.5 深拷贝与浅拷贝



**重难点**  

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



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

    

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

    



**示例:**



class Person {

public:

//无参(默认)构造函数

Person() {

	cout << "无参构造函数!" << endl;

}

//有参构造函数

Person(int age ,int height) {

	cout << "有参构造函数!" << endl;

	m_age = age;

	m_height = new int(height);

}

//拷贝构造函数  

Person(const Person& p) {

	cout << "拷贝构造函数!" << endl;

	//如果不利用深拷贝在堆区创建新内存,会导致浅拷贝带来的重复释放堆区问题

	m_age = p.m_age;

	//m_height = p.m_height;//编译器默认提供的拷贝函数是这一行 浅拷贝

	m_height = new int(*p.m_height);//深拷贝

	

}



//析构函数

~Person() {

	cout << "析构函数!" << endl;

	if (m_height != NULL){

		delete m_height;//浅拷贝时会重复释放同一块内存

	}

}

public:

int m_age;

int* m_height;

};

void test01()

{

Person p1(18, 180);



Person p2(p1);



cout << "p1的年龄: " << p1.m_age << " 身高: " << *p1.m_height << endl;



cout << "p2的年龄: " << p2.m_age << " 身高: " << *p2.m_height << endl;

}

int main() {

test01();



system("pause");



return 0;

}




> 总结:如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题,因为浅拷贝后两个属性指向同一块内存,在调用析构函数释放数据时,会因同一块内存重复释放而运行异常。自己提供深拷贝重新开辟一块新内存存放属性解决这一问题。



#### []( )4.2.6 初始化列表



**作用:**



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



**语法:**`构造函数():属性1(值1),属性2(值2)... {}`



**示例:**



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) {}

void PrintPerson() {

	cout << "mA:" << m_A << endl;

	cout << "mB:" << m_B << endl;

	cout << "mC:" << m_C << endl;

}

private:

int m_A;

int m_B;

int m_C;

};

int main() {

Person p(1, 2, 3);

p.PrintPerson();



system("pause");

return 0;

}




#### []( )4.2.7 类对象作为类成员



C++类中的成员可以是另一个类的对象,我们称该成员为 对象成员



例如:



class A {}

class B

{

A a;

}




B类中有对象A作为成员,A为对象成员



那么当创建B对象时,A与B的构造和析构的顺序是谁先谁后?



**示例:**



class Phone

{

public:

Phone(string name){

	m_PhoneName = name;

	cout << "Phone构造" << endl;

}



~Phone(){

	cout << "Phone析构" << endl;

}



string m_PhoneName;

};

class Person

{

public:

//初始化列表可以告诉编译器调用哪一个构造函数

Person(string name, string pName) :m_Name(name), m_Phone(pName){

	cout << "Person构造" << endl;

}



~Person(){

	cout << "Person析构" << endl;

}



void playGame(){

	cout << m_Name << " 使用" << m_Phone.m_PhoneName << " 牌手机! " << endl;

}



string m_Name;

Phone m_Phone;

};

void test01()

{

//当类中成员是其他类对象时,我们称该成员为 对象成员

//构造的顺序是 :先调用对象成员的构造,再调用本类构造

//析构顺序与构造相反

Person p("张三" , "苹果X");

p.playGame();

}

int main() {

test01();



system("pause");

return 0;

}




#### []( )4.2.8 静态成员



静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员



静态成员分为:



*   静态成员变量

    *   所有对象共享同一份数据

    *   在编译阶段分配内存

    *   类内声明,类外初始化

*   静态成员函数

    *   所有对象共享同一个函数

    *   静态成员函数只能访问静态成员变量



\*\*示例1 :\*\*静态成员变量



//静态成员变量特点:

//1 在编译阶段分配内存

//2 类内声明,类外初始化

//3 所有对象共享同一份数据

class Person

{

public:

static int m_A; //静态成员变量

private:

static int m_B; //静态成员变量也是有访问权限的

};

int Person::m_A = 10;

int Person::m_B = 10;

void test01()

{

//静态成员变量两种访问方式



//1、通过对象

Person p1;

p1.m_A = 100;

cout << "p1.m_A = " << p1.m_A << endl;



Person p2;

p2.m_A = 200;

cout << "p1.m_A = " << p1.m_A << endl; //共享同一份数据

cout << "p2.m_A = " << p2.m_A << endl;



//2、通过类名

cout << "m_A = " << Person::m_A << endl;

//cout << "m_B = " << Person::m_B << endl; //私有权限访问不到

}

int main() {

test01();

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

n::m_A = 10;

int Person::m_B = 10;

void test01()

{

//静态成员变量两种访问方式



//1、通过对象

Person p1;

p1.m_A = 100;

cout << "p1.m_A = " << p1.m_A << endl;



Person p2;

p2.m_A = 200;

cout << "p1.m_A = " << p1.m_A << endl; //共享同一份数据

cout << "p2.m_A = " << p2.m_A << endl;



//2、通过类名

cout << "m_A = " << Person::m_A << endl;

//cout << "m_B = " << Person::m_B << endl; //私有权限访问不到

}

int main() {

test01();

[外链图片转存中…(img-xTPdrXE4-1715623383587)]
[外链图片转存中…(img-ZEeUrs0q-1715623383588)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值