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

【C++】--- 类和对象(上)

类和对象(上)

  • 1. 类的定义
    • 1.1 类定义格式
    • 1.2 访问限定符
    • 1.3 类域
  • 2. 实例化
    • 2.1 实例化概念
    • 2.2 对象大小
  • 3. this指针
  • 4. C和C++中Stack的对比

1. 类的定义

1.1 类定义格式

class是为定义类的关键字,定义类的语法为class 类名 { };,{}中为类的主体,类体中内容称为类的成员类中的变量称为类的属性或者成员变量类中的函数称为类的方法或者成员函数
下面给出一个学生类的简单定义:

classStudent{int_age;int_height;voidprint(){cout<<"这是一个学生类的方法"<<endl;}voidInit(intage,intheight){_age=age;_height=height;}};

为了区分形参和实参,我们一般在成员变量的前面或者后面加上_或者m
我们可以在创建学生类的一个实例

intmain(){Student s1;return0;}

值得一提的是,在C语言中创建一个结构体实例,如果不使用typedef对结构体重命名的话,定义一个学生的结构体需要加上struct关键字,但是在C++中,这不是必要的,类名就是类型,当然结构体名也是类型

structListNode{structListNode*next;intval;};

这是C语言中单链表结点定义方式,C++兼容C的语法。

structListNode{ListNode*next;intval;};

C++就可以这样定义啦!
定义在类中的成员函数默认为inline,现在知道这一点就可以了,后买我们才会较多的使用。

1.2 访问限定符



可以看到,我们无法访问任何一个成员变量和成员方法,它们都是private私有的成员,这就要引出访问限定符了。
C++提供了三种访问限定符,public修饰的成员在类外是可以访问的proctect和private修改时的成员在类外是无法被访问到的,这里protect和private是一样的,后面继承章节才能体现出他们的区别。class定义成员的时候默认的访问限定符为private,所以实例无法访问到类的成员。
下面我们做出修改:

classStudent{private:int_age;int_height;public:voidInit(intage,intheight){_age=age;_height=height;}voidprint(){cout<<"这是一个学生类的方法"<<endl;}};

访问限定符作用域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为⽌,如果后面没有访问限定符,作用域就到}即类结束,所以上述代码就是给Init()print()函数打开了类外的访问权限,这两个函数可以被访问到。

⼀般成员变量都会被限制为private/protected,需要给别人使用的成员函数会放为public。这就要提到类和对象的第一大核心思想:封装类相比于结构体的优势就是实现了方法和变量的集成以及数据的私有化,在C语言中定义一个Stack的话,变量和方法是分别定义的并且变量是裸露的,可以随意访问到的,这就涉及到安全性的问题。C++中类以及访问限定符解决了这个问题,我们把数据私有,只提供方法给外部的用户使用。
C++中的struct也可以定义类,C++兼容C中struct的用法,同时把struct升级为了类,明显的变化是struct中可以定义函数,但是一般情况下,我们推荐使用class来定义类,使用struct定义类成员的时候,默认的访问限定符是public

1.3 类域

在类体外定义成员时,需要使⽤ :: 作用域操作符指明成员属于哪个类域。
例如:规范定义一个栈的时候,在Stack.h文件下的代码如下

#include<iostream>#include<assert.h>usingnamespacestd;classStack{public:voidInit(intn=4);private:int*array;inttop;intcapacity;};

Stack.c的文件的代码如下:

#include"Stack.h"voidStack::Init(intn){array=(int*)malloc(sizeof(int)*n);if(nullptr==array){perror("malloc fail");return;}capacity=n;top=0;}

为什么需要指定作用域呢?类域影响的是编译的查找规则,下⾯程序中Init如果不指定类域Stack,那么编译器就把Init当成全局函数,那么编译时,找不到array等成员的声明/定义在哪⾥,就会报错。指定类域Stack,就是知道Init是成员函数,当前域找不到的array等成员,就会到类域中去查找。

2. 实例化

2.1 实例化概念

  • 用类类型在物理内存中创建对象的过程,称为实例化出对象
  • 类是对象进行⼀种抽象描述,是⼀个模型⼀样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,⽤类实例化出对象时,才会分配空间
    我们后面经常用到的是一个日期类,下面给出他的代码。
#include<iostream>usingnamespacestd;classDate{public:voidInit(intyear,intmonth,intday){_year=year;_month=month;_day=day;}voidPrint(){cout<<_year<<"/"<<_month<<"/"<<_day<<endl;}private:int_year;int_month;int_day;};

这里是日期类的定义,成员变量仅仅是声明,没有开空间。

  • ⼀个类可以实例化出多个对象
intmain(){Date d1;d1.Init(2020,1,1);d1.Print();Date d2;d2.Init(1,1,1);d2.Print();return0;}

类实例化出对象的时候,成员变量随着实例化被定义,才会开空间
这个时候成员变量还没有初始化,不能根据变量是否被初始化来判断变量是否被定义,当变量被开空间意味者变量被定义了。

2.2 对象大小

我们前面说到类被实例化,成员变量就定义成功了,系统就已经给成员变量开了空间,那么成员函数是否被包含呢?

intmain(){Date d1;cout<<sizeof(d1)<<endl;return0;}

类对象大小的确定也要考虑内存对齐,内存对齐规则和结构体的内存对齐一致

d1的大小为12:这说明d1对象中只存储了三个整形的成员变量,成员函数并没有被存储。其实类的成员函数被单独存储在代码段中,其实成员函数没有必要存储在对象中,因为实例化对象的数据是私有的,每个对象的数据可能不同需要单独存储,但是类的成员函数都是相同的,存储在对象中就太浪费了。

classB{public:voidPrint(){//...}};classC{};intmain(){B b;C c;;cout<<sizeof(b)<<endl;cout<<sizeof(c)<<endl;return0;}


我们看到没有成员变量的B和C类对象的大小是1,为什么没有成员函数还要给1个字节呢?这里给1字节,存粹是为了占位表示对象存在,不存储有效数据

3. this指针

intmain(){Date d1;Date d2;d1.Init(2024,3,31);d1.Print();d2.Init(2024,3,4);d2.Print();}

我们对Date类实例化出了两个对象,并分别调用它们的Init和 Print方法。

函数体中没有关于不同对象的区分,那当d1调用Print函数的时候,函数如何知道该访问d1对象还是d2对象呢?这里其实是C++给了一个隐含的this指针解决了这个问题。

//void Init(Date* const this,int year, int month, int day)voidInit(intyear,intmonth,intday){this->_year=year;//一般不会这样来写,这样写一般都是菜鸟选手this->_month=month;this->_day=day;}//void print(Date* const this)voidprint(){cout<<this->_year<<"/"<<this->_month<<"/"<<this->_day<<endl;cout<<_year<<"/"<<_month<<"/"<<_day<<endl;}//d1.Init(&d1,2929, 1, 2);d1.Init(2929,1,2);

其实类的成员函数在编译的时候都会在形参的第一个位置添加一个当前类型的this指针对象在调用成员函数的时候,在实参的第一个位置也把自己的地址传上去了,这样就做到了不同的对象调用相同的成员函数由不同的效果了。
这里提出一点,C++规定不能在实参和形参的位置显式的给出this指针,但是在成员函数体中可以给出

4. C和C++中Stack的对比

C语言实现栈的代码

#include<stdio.h>#include<stdlib.h>#include<stdbool.h>#include<assert.h>typedefintSTDataType;typedefstructStack{STDataType*a;inttop;intcapacity;}ST;voidSTInit(ST*ps,intn){assert(ps);ps->a=(STDataType*)malloc(sizeof(STDataType)*n);if(a==NULL){perror("malloc申请空间失败");return;}ps->top=0;ps->capacity=0;}voidSTDestroy(ST*ps){assert(ps);free(ps->a);ps->a=NULL;ps->top=ps->capacity=0;}//...

C++实现栈的代码

#include<iostream>usingnamespacestd;typedefintSTDataType;classStack{public:// 成员函数voidInit(intn=4){_a=(STDataType*)malloc(sizeof(STDataType)*n);if(nullptr==_a){perror("malloc申请空间失败");return;}_capacity=n;_top=0;}voidDestroy(){free(_a);_a=nullptr;_top=_capacity=0;}//成员方法privateint*_a;int_capacity;int_top;};
  • C++中数据和函数都放到了类里面,通过访问限定符进行了限制,不能再随意通过对象直接修改数据,这是C++封装的⼀种体现,这个是最重要的变化。
  • C++中有些相对方便的语法,比如Init给的缺省参数会方便很多,成员函数每次不需要传对象地址,因为this指针隐式传递了,使用类型不再需要typedef关键字。
  • 这里使用C++实现的栈跟C语言没有本质的差别,但是后面学到STL,用适配器实现Stack的时候就会体现C++的魅力。
http://www.jsqmd.com/news/824210/

相关文章:

  • 车载以太网测试实战:从CAN到TSN的范式转移与工程实践
  • 【GD32F427开发板试用】跨平台嵌入式开发实战:从零构建macOS/Linux下的ARM-GCC + VSCode + PyOCD工作流
  • 【NotebookLM档案学研究辅助实战指南】:20年档案专家亲授AI时代文献管理黄金法则
  • 2026年防爆监控技术:最新权威排名与专业指南。
  • 收藏!小白程序员必看:大模型训练全解析(从预训练到微调)
  • 免费在线去视频水印工具推荐,去本地视频水印怎么去?2026 实测方法汇总 - 爱上科技热点
  • 语音提示工程实战:从原理到应用,解锁AI声音表现力
  • 书匠策AI:一个让论文小白也能“开挂“的毕业论文神器,到底有多能打?
  • 如何把视频转换成音频 简单几步学会无损转换 - 爱上科技热点
  • 干货版《算法导论》04:渐近复杂度与序列接口实战
  • OpenClaw 用户迁移至 Taotoken 平台享受更优 Token 价格
  • 2026实测|下载抖音作品怎么去掉水印?抖音去水印工具推荐与方法全指南 - 爱上科技热点
  • AI Agent安全防御实战:从威胁模型到工程化防护体系
  • 【2024视频生成决策指南】:基于237小时渲染日志、41个商业项目回溯,Sora 2与Runway到底该选谁?
  • Linux内核C语言编程技巧:从零开销抽象到高效并发实战
  • 高效视频转音频方法汇总 日常剪辑必备实用干货 - 爱上科技热点
  • 视频水印怎么去掉?手机电脑去除视频水印教程,2026免费安全方法全盘点 - 爱上科技热点
  • 告别ET1100?用AX58100这颗国产EtherCAT从站芯片,低成本搞定机器人关节控制
  • 一、延迟飙升的幕后黑手
  • QModMaster:为什么这款开源Modbus调试工具能解决你90%的工业通信难题?
  • Translumo终极指南:实时屏幕翻译神器,让你跨越语言障碍的完整教程
  • 教育机构在 AI 编程课程中采用 Taotoken 作为统一实验平台的考量
  • 【Midjourney建筑效果图量产指南】:单日批量生成200+合规效果图的工业化工作流(含AutoCAD→MJ→PS无缝链路)
  • 高清提取视频音频教程,完整保留原声优质音质 - 爱上科技热点
  • 避开PWM输入捕获的坑:STM32G431双定时器(TIM3TIM8)中断回调函数编写详解
  • NAND Flash编程策略:One Shot与Two Pass的性能与可靠性博弈
  • 使用Python快速接入Taotoken实现多模型API调用,告别Claude Code封号烦恼
  • 书匠策AI官网www.shujiangce.com|期刊论文写作这件事,原来可以像“搭积木“一样简单
  • 5个实用技巧:用MouseJiggler彻底解决Windows自动休眠问题
  • 免费照片去水印软件App推荐排行榜丨2026实测:哪款手机去水印工具好用又免费? - 爱上科技热点