2024年C C++最全【C++】打怪升级—,下血本买的

img
img

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

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

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

int _a2;//先初始化 _a2
int _a1;

};

int main()
{
A aa(1);
aa.Print();
}


![image-20221012235921853](https://img-blog.csdnimg.cn/img_convert/79bfb815dc7112bda4b69dc660ffc048.png)


对于初始化列表我们可以简单小结一下:



> 
> 1.尽量使用初始化列表初始化
> 
> 
> 2.一个类尽量提供默认构造。(可以提供全缺省)
> 
> 
> 


#### 3.explicit关键字


构造函数不仅可以构造与初始化对象,**对于单个参数的构造函数,还具有类型转换的作用**



class Date
{
public:
//单参数支持隐式类型的转换
Date(int year)
:_year(year)
{}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2022);
//隐式类型的转换
Date d2 = 2022;//本来是构造(临时)+拷贝构造,会优化成直接构造

const Date& d6 = 2022;
return 0;

}


**用explicit修饰构造函数,将会禁止单参构造函数的隐式转换**



class Date
{
public:
explicit Date(int year)
:_year(year)
{}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2022);
//隐式类型的转换
Date d2 = 2022;
const Date& d6 = 2022;

return 0;

}


![image-20221013095610288](https://img-blog.csdnimg.cn/img_convert/eb62ed1dd2d9a4c3fe0a453f80d5e336.png)


多参数构造——C++11才开始支持



class Date
{
public:
Date(int year, int month, int day)
:_year(year)
,_month(month)
,_day(day)
{}
private:
int _year;
int _month;
int _day;
};

int main()
{
Date d1 = {2022, 10, 13};
const Date& d2 = { 2022,10,13 };
return 0;
}




---


### 二、static成员


#### 1.概念


static的类型有:


* **全局static**
* **局部static**
* **类里面static(static成员变量属于类,并且类的每个对象共享)**


基本概念



> 
> 声明为static**的类成员**称为**类的静态成员**,用static修饰的**成员变量**,称之为**静态成员变量**;用static**修饰**的成员函数\*\*,称之为**静态成员函数**。\*\*静态的成员变量一定要在类外进行初始化
> 
> 
> 


静态成员函数和静态成员变量可以相互配合起来使用


实现一个类,计算中程序中创建出了多少个类对象:


**我们可以在类中声明一个静态成员N用来统计创建多少个类对象,然后在设置一个静态成员函数可以进行调用**,在类外对N进行定义初始化



class A
{
public:
A(int a)
:_a(a)
{
++N;
}
A(const A& aa)
:_a(aa._a)
{
++N;
}
//没有this指针,只能访问静态成员
static int GetN()
{
return N;
}
private:
int _a;

static int N;//声明

};
//生命周期是全局的,作用域受类域控制
int A::N = 0;//定义初始化

void F1(A aa)
{
}

A F2()
{
A aa(1);
return aa;
}

void F3(A& aa)
{
}
int main()
{
A aa1(1);
A aa2 = 2;//优化了,直接构造

A aa3 = aa1;

cout <<aa1.GetN()<< endl;//3
//cout<<A::GetN()<<endl;

F1(aa1);//传值传参调用拷贝构造
cout << aa1.GetN() << endl;//4

F2();
cout << aa1.GetN() << endl;//6

F3(aa1);
cout << aa1.GetN() << endl;//6

cout << A::GetN() << endl;

return 0;

}


#### 2.特性


1. **静态成员为所有类对象所共享,不属于某个具体的实例**
2. **静态成员变量必须在类外定义,定义时不添加static关键字**
3. **类静态成员即可用类名::静态成员或者对象.静态成员来访问**
4. **静态成员函数没有隐藏的this指针,不能访问任何非静态成员**
5. **静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值**


对于静态成员的作用,我们可以来通过一道题目简单理解一下下哈:


[JZ64求1+2+3+…+n]([求1+2+3+…+n\_牛客题霸\_牛客网 (nowcoder.com)](https://bbs.csdn.net/topics/618668825))


![image-20221013180023234](https://img-blog.csdnimg.cn/img_convert/e27e9843cec9585f8f850ad733466fe1.png)


此题我们就可以利用静态成员来完美解决。(用位运算也可以解决)



class Sum
{
public:
Sum()
{
_ret+=_i;
++_i;
}

static int GetRet()
{
    return _ret;
}

private:
static int _i;
static int _ret;

};

int Sum::_i = 1;
int Sum::_ret = 0;

class Solution {
public:
int Sum_Solution(int n) {
Sum arr[n];
return Sum::GetRet();
}
};




---


### 三、C++11成员初始化


C++11支持非静态成员变量在声明时进行初始化赋值,**但是要注意这里不是初始化,这里是给声明的成员变量缺省值**



class B
{
public:
B(int b = 0)
:_b(b)
{}
int _b;
};
class A
{
public:
void Print()
{
cout << a << endl;
cout << b._b << endl;
cout << p << endl;
}
private:
// 非静态成员变量,可以在成员声明时给缺省值。
int a = 10;
B b = 20;
int* p = (int*)malloc(4);
static int n;
};
int A::n = 10;
int main()
{
A a;
a.Print();
return 0;
}




---


### 四、友元



> 
> 友元分为:**友元函数**和\*\*友元类  
>  友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。
> 
> 
> 


#### 1.友元函数


在日期类重载operator<< ,我们就谈过友元了。友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。 下面通过一个代码来看看是如何使用的:



class Date
{
friend ostream& operator <<(ostream& cout, const Date& d);
friend istream& operator>>(istream& cin, Date& d);
public:
Date(int year, int month, int day)
: _year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
ostream& operator <<(ostream& cout, const Date& d)
{
cout << d._year << “-” << d._month << “-” << d._day;
return cout;
}
istream& operator>>(istream& cin, Date& d)
{
cin >> d._year;
cin >> d._month;
cin >> d._day;
return cin;
}



> 
> **友元函数可访问类的私有和保护成员,但不是类的成员函数**
> 
> 
> **友元函数不能用const修饰**
> 
> 
> **友元函数可以在类定义的任何地方声明,不受类访问限定符限制**
> 
> 
> **一个函数可以是多个类的友元函数**
> 
> 
> **友元函数的调用与普通函数的调用和原理相同**
> 
> 
> 


#### 2.友元类


友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。


* **友元关系是单向的,不具有交换性**


比如在Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。


* **友元关系不能传递**


如果B是A的友元,C是B的友元,则不能说明C是A的友元。



class Date; // 前置声明
class Time
{
friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变量
public:
Time(int hour, int minute, int second)
: _hour(hour)
, _minute(minute)
, _second(second)
{}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
,_t(1,1,1)
{}
void SetTimeOfDate(int hour, int minute, int second)
{
// 直接访问时间类私有的成员变量
_t._hour = hour;
_t._minute = minute;
_t._second = second;
}
private:
int _year;
int _month;
int _day;
Time _t;
};




---


### 五、内部类


#### 概念及特性


概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。注意此时这个内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去调用内部类。外部类对内部类没有任何优越的访问权限


比如下面的例子,B可以访问A,A不可以访问B


注意:内部类就是外部类的友元类。注意友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。



//相当于两个独立的类
//B类的访问受A的类域和访问限定符的限制
class A
{
private:
static int k;
int _a;
public://B天生就是A的友元
class B
{
int _b;
public:
void foo(const A& a)
{
cout << k << endl;
cout << a._a << endl;
}
};
};
int A::k = 1;
int main()
{
cout << sizeof(A) << endl;
A aa;
A::B bb;
bb.foo(A());
return 0;
}




---


### 六、匿名对象


什么是匿名对象呢?**废话不多说,我们直接进入代码实践**👇



class A
{
public:
A(int a = 0)
:_a(a)
{
cout << “A(int a)” << endl;
}
~A()
{
cout << “~A()” << endl;
}
private:
int _a;
};
int main()
{
//有名对象
A aa0;
A aa1(1);
A aa2 = 2;
//匿名对象——生命周期只在当前这一行
A();
A(3);
return 0;
}


![image-20221013223652976](https://img-blog.csdnimg.cn/img_convert/117ea79f001af4808ba10386b11aa477.png)


匿名对象在特定的场景之下使我们更加方便(偷懒):



A func()
{
//通常方式
//A ret(10);
//return ret;

//匿名对象
return A(10);

}




---


### 七、编译器优化


**在传参和传返回值的过程中,一般编译器会做一些优化,减少对象的拷贝,我们可以对一些场景进行简单的分析**:内容较繁琐



class A
{
public:
A(int a = 0)
:_a(a)
{
cout << “A(int a)” << endl;
}
A(const A& aa)
:_a(aa._a)
{
cout << “A(const A& aa)” << endl;
}
A& operator = (const A& aa)
{
cout << “A& operator = (const A& aa)” << endl;
if (this != &aa)
{
_a = aa._a;
}
return *this;
}
~A()
{
cout << “~A()” << endl;
}
private:
int _a;
};

void f1(A aa)
{

}

int main()
{
//优化场景1:
//A aa1 = 1; //A tmp(1) A aa1(tmp)—>构造+拷贝构造———>优化 A aa1(1)

//优化场景2:
//A aa1(1);构造
//f1(aa1);拷贝构造
f1(A(1));//构造匿名对象+拷贝构造——>优化,直接构造

return 0;

}


对于优化场景1:我们知道,隐式转化会构造一个临时对象tmp(1),然后再去进行拷贝构造,但是编译器在这个地方进行了优化,只需要构造一次就足矣。


对于优化场景2:对于匿名对象类,我们需要构造匿名对象,还需要进行拷贝构造,但是这里也进行了优化,构造。



![img](https://img-blog.csdnimg.cn/img_convert/5293eab0eb8a3447209e28111770f809.png)
![img](https://img-blog.csdnimg.cn/img_convert/a74836c4970eb8415ffcc8c5603b336b.png)

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

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

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

 _a;
};

void f1(A aa)
{

}

int main()
{
    //优化场景1:
	//A aa1 = 1; //A tmp(1) A aa1(tmp)--->构造+拷贝构造———>优化 A aa1(1)

	//优化场景2:
	//A aa1(1);构造
	//f1(aa1);拷贝构造
	f1(A(1));//构造匿名对象+拷贝构造——>优化,直接构造
    
	return 0;
}

对于优化场景1:我们知道,隐式转化会构造一个临时对象tmp(1),然后再去进行拷贝构造,但是编译器在这个地方进行了优化,只需要构造一次就足矣。

对于优化场景2:对于匿名对象类,我们需要构造匿名对象,还需要进行拷贝构造,但是这里也进行了优化,构造。

[外链图片转存中…(img-IcRrLUe7-1715532783233)]
[外链图片转存中…(img-B6a81ukJ-1715532783234)]

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值