C++类和对象你真的听懂了吗?来,看完这篇保姆级类和对象教程,保证你在学校杀疯——上篇
“长风破浪会有时,直挂云帆济沧海”
🚀作者:编程路上一只狗
🚀博客主页:编程路上一只狗
🚀归属专栏:C++学习这里还会更新c++其余的学习教程哦,会随着学习不断地深入而更新的
🚀想叨叨几句:我是大一计科专业的学生,CSDN新人一枚,我会记录自己的学习日常,并且帮助大家查漏补缺,点点关注不迷路哦,多多支持,在学习的道路上大家共同进步!如果有地方出现错误或者不足,还望在评论区留言或者私信,我们一起交流进步!respect,向你致敬。
目录
一、类与对象(上)
2.类的引入
3.类的定义
3.1类的定义语法
3.2类的两种定义方式
4.类的访问限定符以及封装
4.1访问限定符
4.2经典面试问题
4.3封装
5.类的作用域
6.类的实例化
7.类对象模型
7.1计算类的大小
7.2结构体内存对齐规则
8.this指针
8.1this指针的引出
8.2this指针的特性
二.未完待续
一、类与对象(上)
在学习类和对象之前我么们要知道
C语言是 面向过程的, 关注的是 过程,分析出求解问题的步骤,通过函数调用逐步解决问题。 C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
怎么理解呢,我给大家举个例子:
外卖系统
面向过程:下单、接单、送餐的三个过程。
面向对象:客户、商家、骑手,并且关注的是这三个对象 之间的关系
2.类的引入
在c语言的学习中,我们已经学了结构体,但是在c语言的规定中结构体只能定义变量,但是C++中在结构体中不仅可以定义变量,也可以定义函数。
struct Student{ void InitStudentInfo(const char* name, const char* gender, int age) { strcpy(_name, name); strcpy(_gender, gender); _age = age; } void PrintStudentInfo() { cout<<_name<<" "<<_gender<<" "<<_age<<endl; } char _name[20]; char _gender[3]; int _age;};
那么在C++中类就有两种定义方式其中一种就是struct,但是在c++中我们更习惯用class定义类。
3.类的定义
3.1类的定义语法
class className{ // 类体:由成员函数和成员变量组成 }; // 一定要注意后面的分号
class 为 定义类的 关键字(不可更改), ClassName 为类的名字(随意更改), {} 中为类的主体,注意 类定义结束时后面 分号 。 类中的元素称为 类的成员: 类中的 数据 称为 类的属性 或者 成员变量 ; 类中的 函数 称为 类的方法 或者 成员函数
3.2类的两种定义方式
1.声明和定义全部放在类中
struct Student{ void InitStudentInfo(const char* name, const char* gender, int age) { strcpy(_name, name); strcpy(_gender, gender); _age = age; } void PrintStudentInfo() { cout<<_name<<" "<<_gender<<" "<<_age<<endl; } //以上两个函数就是声明和定义放在一起 char _name[20]; char _gender[3]; int _age;};
2.声明和定义分离(声明.h定义.cpp)
以下为了方便演示就在类外面定义的,大家了解就行,注意要加上类的作用域Student::
struct Student{ void InitStudentInfo(const char* name, const char* gender, int age); void PrintStudentInfo(); //以上两个函数就是声明 char _name[20]; char _gender[3]; int _age;};void Student::InitStudentInfo(const char* name, const char* gender, int age) { strcpy(_name, name); strcpy(_gender, gender); _age = age; }void Student::PrintStudentInfo(){ cout<<_name<<" "<<_gender<<" "<<_age<<endl;}
以上两种方式各有好处,但是一般在项目工程中我们一般采用第二种。
4.类的访问限定符以及封装
4.1访问限定符
C++ 实现封装的方式: 用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其 接口提供给外部的用户使用 。 访问限定符说明: 1. public 修饰的成员在类外可以直接被访问 2. protected 和 private 修饰的成员在类外不能直接被访问 ( 此处 protected 和 private 是类似的 ) 3. 访问权限 作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止 4. class 的默认访问权限为 private , struct 为 public( 因为 struct 要兼容 C) 注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别
4.2经典面试问题
【面试题】 问题: C++ 中 struct 和 class 的区别是什么? 解答: C++ 需要兼容 C 语言,所以 C++ 中 struct 可以当成结构体去使用。另外 C++ 中 struct 还可以用来定义类。 和 class 是定义类是一样的,区别是 struct 的成员默认访问方式是 public , class 是 struct 的成员默认访问方式 是 private 。
4.3封装
面向对象的三大特性: 封装、继承、多态 。 在类和对象阶段,我们只研究类的封装特性,那什么是封装呢?
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
5.类的作用域
类定义了一个新的作用域 ,类的所有成员都在类的作用域中 。 在类体外定义成员,需要使用 :: 作用域解析符指明成员属于哪个类域。
struct Student{ void InitStudentInfo(const char* name, const char* gender, int age); void PrintStudentInfo(); char _name[20]; char _gender[3]; int _age;};void Student::InitStudentInfo(const char* name, const char* gender, int age)//类的作用域 { strcpy(_name, name); strcpy(_gender, gender); _age = age; }void Student::PrintStudentInfo()//使用了类的作用域{ cout<<_name<<" "<<_gender<<" "<<_age<<endl;}
6.类的实例化
用类类型创建对象的过程,称为类的实例化 1.类只是一个模型,如果不实例化,那么就没有实际分配内存空间来储存它 2.一个类呢是可以实例话出多个对象的,实例化的对象才会真正的分配到物理空间,储存类成员变量 3.打个比方将实例化对象比作大桥,那么类就像是设计图纸(并没有实体建筑的存在),靠着图纸才能造出一个个桥梁
7.类对象模型
7.1计算类的大小
问题:类中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?如何计算一个类的大小? 在类中只保存成员变量大小,而函数是放在代码公共区域的。 我们可以通过下面的不同类的大小来分析
// 类中既有成员变量,又有成员函数class A1 {public: void f1(){}private: int _a;};// 类中仅有成员函数class A2 {public: void f2() {}};// 类中什么都没有---空类class A3{};
sizeof(A1) : _4_ sizeof(A2) : _1_ sizeof(A3) : _1_有的同学可能就会有疑问,你不是说 只保存成员变量大小吗,为啥A2和A3是1 这就是因为虽然A2和A3没有任何成员变量,但是他们需要有一个空间,来证明他们是存在的,如果没有任何空间分配给他们的话,那岂不是不存在这个类了。所以空类要分到 一个字节的空间
7.2结构体内存对齐规则
我们在学习c语言的时候已经学习了结构体的内存对齐规则, 类的大小计算规则和结构体是一样的 1. 第一个成员在与结构体偏移量为 0 的地址处。 2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS 中默认的对齐数为 8 3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。 4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是 所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
8.this指针
8.1this指针的引出
我们先用日期类来举一个例子:
class Date{ public : void Display () { cout <<_year<< "-" <<_month << "-"<< _day <<endl; } void SetDate(int year , int month , int day) { _year = year; _month = month; _day = day; }private : int _year ; // 年 int _month ; // 月 int _day ; // 日};int main(){ Date d1, d2; d1.SetDate(2018,5,1); d2.SetDate(2018,7,1); d1.Display(); d2.Display(); return 0; }
对于上述类,有这样的一个问题: Date类中有SetDate与Display两个成员函数,函数体中没有关于不同对象的区分,那当s1调用SetDate函数时,该函数是如何知道应该设置s1对象,而不是设置s2对象呢?C++中通过引入this指针解决该问题 ,即: C++ 编译器给每个 “ 非静态的成员函数 “ 增加了一个隐藏的指针参 数,让该指针指向当前对象 ( 函数运行时调用该函数的对象 ) ,在函数体中所有成员变量的操作,都是通过该 指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成 。也就是说编译器会增加一个 隐藏的参数
这里要注意哦
1.this指针是隐含的 ,是编译器编译的时候加的,但是我们并不能在显示和调用的时候自己添加
2.可以在成员函数中成员可以使用this指针(自己显示的加出来)
8.2this指针的特性
1. this 指针的类型:类类型 * const 2. 只能在 “ 成员函数 ” 的内部使用 3. this指针本质上其实是一个成员函数的形参 ,是对象调用成员函数时,将对象地址作为实参传递给 this 形参。所以 对象中不存储this指针 。 4. this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递
二.未完待续
此次类和对象将会分三个文章写,上篇中篇和下篇,如果喜欢的小伙伴们可以关注一下我哦,后续我将会分享更多学习内容,如果有什么疑问可以在评论区留言或者私信我,我看见就会回复哦!
创作打卡挑战赛
赢取流量/现金/CSDN周边激励大奖