当前位置: 首页 > news >正文

C++ 篇 类和对象(1)万能工具怎么用?

🎬 胖咕噜的稞达鸭:个人主页

🔥 个人专栏: 《数据结构》

⛺️技术的杠杆,撬动整个世界!

在这里插入图片描述

一.类的定义

  1. 类定义格式
  • class为定义类的关键字,Stack为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的方法或者成员函数
#include<iostream>
#include<assert.h>
using namespace std;//class 定义类的关键字,stack 是类的名字,{ }中为类的主体
class Stack
{
public://成员函数void Init(int n = 4){array = (int*)malloc(sizeof(int) * n);if (nullptr == array){perror("malloc申请空间失败");return;}capacity = n;top = 0;}void Push(int x){//扩容array[top++] = x;}int Top(){assert(top > 0);return array[top - 1];}void Destroy(){free(array);array = nullptr;top = capacity = 0;}private://成员变量    private表示其一下的内容不可修改int* array;//栈中的数组size_t capacity;size_t top;
};//这个分号不可省略int main()//没有返回值也不可写void!!!
{Stack st;//类型可以访问 //st是栈对象st.Init();//通过对象成员函数()调用,编译器会隐式传递this指针(指回当前对象),让成员函数能访问对象的私有成员st.Push(1);st.Push(2);//栈顶为2,栈底为1cout << st.Top() << endl;//  << 输出  通过cout输出到控制台st.Destroy();return 0;
}
  • 为了区分成员变量,一般习惯上成员变量会加一个特殊标识,如成员变量前面或者后面加_或者_m开头,注意C++中这个并不是强制的。
class Date
{
public://成员函数void Init(int year, int month, int day){_year = year;_month = month;_day = day;}
private://成员变量//加一个特殊标记,_或者_m开头int _year;int _month;int _day;
};int main()
{Date d;d.Init(2025, 9, 18);return 0;
}
  • C++中struct也可以定义类,C++兼容C中struct的用法,同时struct升级成了类,明显的变化是struct中可以定义函数,一般情况下我们还是推荐用class定义类。
typedef int STDataType;
typedef struct ListNode
{int val;struct ListNode* next;
}LTnode;
#include<iostream>
using namespace std;struct ListNodeCPP
{//成员函数void Init(int x){next = nullptr;val = x;}//成员变量ListNodeCPP* next;int val;
};int main(){return 0;}

定义在类面前的成员函数默认为inline。

  1. 访问限定符
三种public
访问private
限定符protected
public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能被直接访问,private和protected是一样的。
访问权限作用域从该访问限定符开始的位置到下一个访问限定符的出现时为止,如果后面没有访问 限定符,作用域到}就结束。
class定义成员没有被访问限定符修饰的时候默认为private,struct默认为public。
  1. 类域
#include<iostream>
using namespace std;
class Stack
{
public:// 成员函数void Init(int n = 4);
private:// 成员变量int* array;size_t capacity;size_t top;
};
// 声明和定义分离,需要指定类域
void Stack::Init(int n)//说明Init不是一个全局函数,是类的成员函数
{array = (int*)malloc(sizeof(int) * n);if (nullptr == array){perror("malloc申请空间失败");return;}capacity = n;top = 0;
}
int main()
{Stack st;st.Init();return 0;
}

面试题插入:说出声明和定义的区别:
声明就是告诉变量的类型;定义要开空间。

二.实例化

在这里插入图片描述

  • 什么是实例化
    类是对象进行一种抽象描述,是一个模型一样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,用类实例化出对象时,才会分配空间。类和实例化对象的关系相当于一张图纸和许多建筑的关系。
  • 对象大小
    Date实例化d1和d2两个对象,d1和d2都有各自独立的成员变量_year/_month/_day存储各自的数据,但是d1和d2的成员函数Init/Print指针却是一样的,存储在对象中就浪费了。
    调用函数被编译成汇编指令[call地址],其实编译器在编译链接时,就要找到函数的地址,不是在运行时找,只有动态多态是在运行时找,就需要存储函数地址。
  • 内存对齐规则
  • [1 ] 第一个成员在与结构体偏移量为0的地址处,
  • [2 ] 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处
  • [ 3] 注意:对齐数=编译器默认的一个对齐数与该成员大小的较小值。
  • [ 4] VS中默认的对齐数为8
  • [ 5] 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
  • [ 6] 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

下面给三个例子算一下实例化对象分别有多大?

#include<iostream>
using namespace std;// 计算一下A / B / C实例化的对象是多大?
class A 
{ 
public:void Print(){ cout << _ch << endl;}
private:char _ch; int _i;
};
class B 
{
public:void Print() {//...}
};
class C
{};
int main()
{A a;B b;C c;cout << sizeof(a) << endl;cout << sizeof(b) << endl;cout << sizeof(c) << endl; //1B和C大小一致,虽然没有成员变量的类,但是它存在就要开空间,给一个字节,纯粹就是为了占位标记return 0;
}

在这里插入图片描述
在这里插入图片描述

三.this指针

C++规定不能在实参和形参的位置显示的写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针。

#include<iostream>
using namespace std;
class Date
{
public:// void Init(Date* const this, int year, int month, int day)//所有成员函数都会增加隐含的this指针void Init(int year, int month, int day){this->_year = year;this->_month = month;this->_day = day;}// void Print(Date* const this)void Print(){cout << this->_year << "/" << this->_month << "/" << _day << endl;}private:// 这里只是声明,没有开空间int _year;int _month;int _day;
};int main()
{// Date类实例化出对象d1和d2Date d1;Date d2;// d1.Init(&d1, 2024, 3, 31);d1.Init(2024, 3, 31);// d1.Print(&d1);d1.Print();// d2.Init(&d2, 2024, 7, 5);d2.Init(2024, 7, 5);// d2.Print(&d2);d2.Print();//不可以写成d2.Print(d2);//但是可以在函数体内写return 0;
}

下面以两个选择题结束今天的学习
1.这段代码会编译运行结果是()

#include<iostream>
using namespace std;class A
{
public:void Print(){//cout << this << endl;cout << "A::Print()" << endl;}
private:int _a;
};int main()
{A* p = nullptr;// mov ecx  pp->Print(); // call  地址//p->_a = 1;return 0;
}

在这里插入图片描述
在这里插入图片描述
2.下面程序编译运行的结果是编译报错为什么?

#include<iostream>
using namespace std;class A
{
public:void Print(){cout << "A::Print()" << endl;cout << _a << endl;//_a需要存在对象A里面,这里访问_a是通过this来访问的(相当于解引用)}
private:int _a;
};int main()
{A* p = nullptr;// mov ecx  pp->Print(); // call  地址//调用Print函数传参,把P传给ecx,call位置是地址,地址不存对象P里面,不存在解引用//不会从对象里面找,地址是在编译的时候就确定的return 0;
}

在这里插入图片描述

http://www.dtcms.com/a/390881.html

相关文章:

  • Ansible-copy模块
  • SAPO去中心化训练:多节点协作让LLM训练效率提升94%
  • Stm32 IAP 升级
  • 5G标准学习笔记17------ MDT(Minimization of Drive Tests)路测最小化
  • [Dify] 构建“流程型表单问答”系统:逐步提问逻辑实现
  • 从RAW到JPG到BMP:工业视觉图像格式怎么选?
  • Linux系统Rsync+sersync 实现数据同步
  • 【13/20】缓存与性能优化:Redis 在 Express 中的整合,实现用户数据缓存
  • 如何防止电脑长时间运行过热?定时关机是第一道防线
  • 开源监控利器Prometheus+Grafana在银河麒麟操作系统的落地实践
  • 小程序移动端设计UI(一)预约小程序——东方仙盟练气期
  • Android13 命令启用WLAN详细日志分析
  • 临床AI产品化全流程研究:环境聆听、在环校验与可追溯系统的多技术融合实践(中)
  • 深度解读昇腾CANN动态Shape图调度加速技术
  • linux系统使用ImageMagick注意,只能使用convert命令
  • [Windows] 搜狗拼音一键净化
  • Go语言25个关键字全解析
  • 图像滤波常用总结
  • Go语言设计原则与设计模式
  • (LoRA深度解析)LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS论文精读(逐段解析)
  • 第十四届蓝桥杯青少组C++选拔赛[2022.11.27]第二部分编程题(4、找路线)
  • 知识图谱对自然语言处理深层语义分析的影响与启示:结构化研究报告
  • 架构师成长之路-缓存二
  • 正点原子小智BOX0/BOX2 产品使用视频表情功能
  • 鸿蒙NEXT分布式文件系统:开启跨设备文件访问新时代
  • 【主机初始化工作】
  • Ubuntu20.04仿真 | iris四旋翼添加livox mid360激光雷达
  • Linux进程终止
  • Go如何重塑现代软件开发的技术基因
  • 设计模式(C++)详解—外观模式(2)