网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用 ::
作用域解析符指明成员属于哪个类域。
2.1函数声明和定义分离
和普通的函数一样,类同样支持声明和定义分离。下面的代码中,我并没有分离函数的声明和定义
- 成员函数在类里面定义,编译器会默认处理为内联函数
class Student{
void Print()
{
cout<<_name<<" "<<_sex<<" "<<_age<<" "<<_phone<<endl;
}
char _name[20];
char _sex[8];
int _age;
char _phone[20];
};
如果需要在.h
中写入类的定义,类外面的.cpp
中编写类里面的函数,就需要用到类似于命名空间的使用方法::
class Student{
void Print();//声明函数
char _name[20];
char _sex[8];
int _age;
char _phone[20];
};
在另外的源文件中定义函数
#include "Student.h"
void Student::Print()
{
cout<<_name<<" "<<_sex<<" "<<_age<<" "<<_phone<<endl;
}
当我们编写大型项目的时候,一般都会采用声明和定义分离的方式来编写源码,这样可以更方便他人快速查阅我们的头文件,理解代码的“大纲”
这样看起来好像和以前的方式没啥区别。但当我们引入访问权限的概念后,一切都变啦!
2.2访问限定符
class的默认访问权限是私有;struct默认为公有
你不知道什么是访问权限?那就继续往下看👇
我们可以用public
和private
这两个访问限定符来表明某一个具体类型的共有还是私有。它们的最大区别就是在这个类的外部能不能访问
- public成员可以在类外面直接使用
- protected和private修饰的成员只能在类里面访问
- 访问权限的作用域是从该访问限定符出现,到下一个访问限定符出现为止
- 访问限定符是在编译过程中处理的,并不影响数据在内存上的存放
在前期学习的时候,我们可以认为protected
和private
是相同作用的
class Student{
public:
//函数在类里面定义,编译器默认为内联函数
void Print()
{
cout<<_name<<" "<<_sex<<" "<<_age<<" "<<_phone<<endl;
}
void Init(const char \* name,const char\*sex, int age,const char\* phone)
{
strcpy(_name,name);
strcpy(_sex,sex);
_age=age;
strcpy(_phone,phone);
}
//函数在类里面声明
void Delet();
private:
//这个是对变量的声明
//变量的声明:没有开辟空间
//变量的定义:开辟了空间来存放内容
char _name[20];
char _sex[8];
int _age;
char _phone[20];
//在创建对象的时候定义
};
- 数据和方法分装到一个类里面
- 想给你自用访问的(如函数接口)设置为共有
- 不想给你访问的(如通讯录每个用户的信息类型)设置为私有
这样可以做到,当函数定义修改之后,只要不修改函数声明,就不需要修改main函数中函数的调用!
这叫做:高内聚,低耦合
2.3封装
为什么会有权限的出现呢?我们可以细想一下下面这个场景:
假设我们编写了一个数组栈的代码,里面有一个top用来标明栈顶的元素位置。一般可以把top定义为0或者1,但是这两种方法的函数使用是不同的!如果有那个铁憨憨跑过来,非要把那个top的定义给改掉,那整个代码就废掉不能用辣!
设立私有和公有的初衷,就是为了避免这种情况。开放一些共有函数供类外面访问,这样对整个代码的访问会变得易于管理。当我们自己修改类里面的代码时,只需要做好处理,就不会影响类外面的函数调用(否则就是直接推翻重写了)
这便是我们常常提到的封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
3.类的实例化
用类类型创建对象的过程,称为类的实例化
- 类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它
- 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
类就好比一个毛坯房,现在毛坯房建好了,要想它变得精致,我们还需要在main中调用这个类,不然毛坯房就要变成烂尾楼了
Student p1;
p1.Init("牛爷爷","男",58,"13251341680");
p1.Print();
4.计算类的大小
一般有4种类:包含函数和变量的、只包含函数的、只包含成员变量的、空类
让我们来康康如何计算这些类的大小,解析见注释哦!
其实只需要记住,空类和只有函数的类会有1个字节的空间。计算类的空间的时候不会计算函数大小,成员变量的大小计算遵循结构体内存对齐的计算方法就行了!
#include<iostream>
using namespace std;
class A1{
public:
void func1()
{
int ret=3;
return ;
}
};
class A2{
};
class A3{
public:
char _a;
};
5.this指针
5.1特点
当你用同样的图纸建了很多个屋子后,有没有想过应该如何区分它们呢?
C++在设计这部分的时候,添加了一个this指针来解决这个问题:
C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参 数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
- this指针的类型:
类名* const
- 只能在“成员函数”的内部使用
- this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this 形参。所以对象中不存储this指针。
- this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递
5.2显式使用this
就用下面这个函数举例
void Print()
{
cout<<_name<<endl;
cout<<_sex <<endl;
}
实际上,在调用它的时候,编译器会做如下处理
void Print(Student\*const this)
{
cout<<this->_name<<endl;
cout<<this->_sex <<endl;
}
因为只有这样,才能完整的区分两个不同的类
进一步看看下面这个代码,可以帮助你理解this指针
bool operator==(const Date& d){
return _year == d._year
&& _month== d._month
&& _day == d._day;
}
这是一个日期的比较函数,是操作符重载(后面会讲到)
你可以看到,这个函数我们传入了一个Date类型的引用,这是区别于this的另外一个类的对象
如果没有this,那就很难区分两个变量的_year
,于是编译器会把它优化成下面这样,就不会存在无法区分的问题了
bool operator==(Date\*const this,const Date& d){
return this->_year == d._year
&& this->_month== d._month
&& this->_day == d._day;
}
5.3空指针问题
int main()
{
int x=10;
//在程序中,访问NULL不会报错,但是解引用Null会报错
int\*a=NULL;
int\*b=&x;
//a=x;//err
\*b=20;
return 0;
}
#include<iostream>
using namespace std;
class ta{
public:
void Print()
{
cout<<"print ta"<<endl;
//cout<<\_a<<endl;
}
private:
int _a;
};
int main()
{
ta\* p=nullptr;
p->Print();
//可以去访问空指针的函数
//因为函数只是去调用了类里面的Print函数
//同时传了一个p的this指针(空指针传参是不会报错的)
//但是如果你去访问p里面\_a变量,就会报运行错误
return 0;
![img](https://img-blog.csdnimg.cn/img_convert/a061005aeaa9d4dda7e6eb8c4c0bfc03.png)
![img](https://img-blog.csdnimg.cn/img_convert/8d980f38748722ca0b2b1d8052015795.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**
//同时传了一个p的this指针(空指针传参是不会报错的)
//但是如果你去访问p里面\_a变量,就会报运行错误
return 0;
[外链图片转存中...(img-OPVPP401-1715821020668)]
[外链图片转存中...(img-cjWLWJ6i-1715821020668)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**