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

C++:类和对象 I(访问限定符、this指针)

目录

类的定义

类的大小

访问限定符

实例化

this指针



 

类的定义

class就是类,class是C++中的一个关键字

当然类也可以是C语言中的struct,C++兼容struct,甚至还有一些升级

定义类的方式

class Date
{};

和C语言的struct一样,class是C++中定义类的一个关键字,Date是这个类的名字,我们需要在后面跟上一个 {}和;,{}里面可以放变量,函数等

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

类的大小

class和struct的大小计算方式一致,和在C语言时的计算方法一致,以下博客有结构体的大小计算讲解

C语言:自定义类型:结构体-CSDN博客

明明C++的类和C语言不同,C语言只能放变量,C++不仅能放变量还能放函数,为什么还是按照C语言的方式只计算成员变量的方法来计算结构体的大小呢?

这是因为成员函数实际上并不存储在类的实例的内存空间中,它们存储在代码段内,而类的实例只存储成员变量

为什么存储在代码段?

因为在类外我们是需要定义多个该类的变量的,例如日期类:

#include<iostream>
using namespace std;class Date
{
public:// ...
private:int _year;int _month;int _day;
};int main()
{Date d1;Date d2;Date d3;// ...return 0;
}

每个日期类对象d1、d2、d3毋庸置疑一定要有它们专属的变量(_year、_month、_day),这才能让它们三个都有各自的日期

那为什么不要每一个日期类对象都有一个成员函数?因为浪费

我们只需要一个函数足以,这个函数就存储在代码段中,当它们需要这个函数时就去代码段中调用这个函数,将它们专有的成员变量传过去即可,那么怎么传呢?具体看下面this指针的讲解

访问限定符

这是跟C语言不同的地方,C语言没有访问限定符的概念,比较自由

是C++一种实现封装的方式,通过访问限定符选择性的将接口给外部的用户使用

有三种访问限定符:public、private、protected

具体使用方法如下: 

class Date
{
public:void Print(){cout << _year << "/" << _month << "/" << _day << endl;}private:int _year;int _month;int _day;
};

public的意思是公有的,公有的就代表可以被外部所访问,例如在main函数中可以使用

private的意思是私有的,私有的就代表不可以被外部所访问,一般都设置成员变量为私有的

protected是受保护的,它发挥作用的地方在继承的那部分,其他和private一致,不能被外部所访问

在继承中,protected外部不能访问,但是它的派生类(子类)可以访问到protected的内容,而private依旧不能访问

 class定义成员没有被访问限定符修饰时默认为private,struct则默认为public,这也是他们在C++中的区别

我们要怎么访问类里面呢?

class Date
{
public:void Print();private:int _year;int _month;int _day;
};void Date::Print()
{cout << _year << "/" << _month << "/" << _day << endl;
}int main()
{Date d1;d1.Print();return 0;
}

这是在类里面声明了Print()函数,在类外面定义了Print()函数

要注意的就是我们需要用::访问限定符访问Date里面,这样才能知道函数内部的_year、_month、_day是谁

访问函数只需要用 . 即可

实例化

class Date
{
public:void Print();// ...private:int _year;int _month;int _day;
};int main()
{Date d1;d1.Print();return 0;
}

在这个日期类中,private里的成员函数都只是声明,并不是定义,并没有开空间,所以他们不是实例化,他们就像一张图纸,只可以看不可以做

而下面的d1就是实例化出了一个日期类对象,可以使用它里面的成员函数

this指针

#include<iostream>
using namespace std;class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}private:int _year;int _month;int _day;
};int main()
{Date d1;Date d2;d1.Init(2024, 7, 12);d1.Print();return 0;
}

在上面的代码中,有了Date类的初始化函数Init,和打印函数Print,这样我们就可以给一个Date对象初始化和打印了

运行结果:

前面有说既然类里面的函数只存在代码区只需要一份共同调用即可,那我们使用d1对象调用的时候函数里面怎么拿到d1的成员变量?为什么不是d2?

这里其实C++隐含了一个this指针,是利用了this指针解决了这个问题

我们的函数其实可以写成这样

class Date
{
public:void Init(int year, int month, int day){this->_year = year;this->_month = month;this->_day = day;}void Print(){cout << this->_year << "/" << this->_month << "/" << this->_day << endl;}private:int _year;int _month;int _day;
};

照样可以运行成功,结果一样

其实函数主题和调用相当于这样

void Init(Date* const this, int year, int month, int day)
{this->_year = year;this->_month = month;this->_day = day;
}void Print(Date* const this)
{cout << this->_year << "/" << this->_month << "/" << this->_day << endl;
}int main()
{Date d1;d1.Init(&d1, 2024, 7, 12);d1.Print(&d1);return 0;
}

但实际上我们是不能这样自己显式的把this写在函数参数上的,编译器会报错

这些都是编译器帮我们做的是,编译器自动的把d1的地址传过去,自动用this指针访问了,所以我们不需要写

但是函数内部我们是可以使用这个this指针的,因为后续我们需要这个this指针,并不只是上面单纯的初始化、打印之类的


相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 租用海外服务器需要考虑哪些因素
  • STM32入门开发操作记录(一)——新建工程
  • “好物”推荐+Xshell连接实例+使用Conda创建独立的Python环境
  • 通过git将文件push到github 远程仓库
  • windows信息收集和提权
  • jitsi 使用JWT验证用户身份
  • AI克隆声音,基于函数计算部署GPT-Sovits语音生成模型
  • 亚马逊erp有店铺不知道怎么上传产品的看过来!
  • shell从入门到精通(只需要这篇就够了)
  • 本地部署 EVE: Unveiling Encoder-Free Vision-Language Models
  • 前端部署自动上传资源文件到cdn/oss 解决路由和访问慢的问题
  • Hadoop3:HDFS-通过配置黑白名单对集群进行扩缩容,并实现数据均衡(实用)
  • DOM 实例:深入理解文档对象模型
  • Android --- 运行时Fragment如何获取Activity中的数据,又如何将数据传递到Activity中呢?
  • 初识c++(命名空间,缺省参数,函数重载)
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • 【node学习】协程
  • 11111111
  • 3.7、@ResponseBody 和 @RestController
  • bearychat的java client
  • JAVA 学习IO流
  • Koa2 之文件上传下载
  • LeetCode29.两数相除 JavaScript
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • spring security oauth2 password授权模式
  • Vue--数据传输
  • windows-nginx-https-本地配置
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 《天龙八部3D》Unity技术方案揭秘
  • ​1:1公有云能力整体输出,腾讯云“七剑”下云端
  • ​Spring Boot 分片上传文件
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • (1)STL算法之遍历容器
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (31)对象的克隆
  • (搬运以学习)flask 上下文的实现
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (转)C#调用WebService 基础
  • (转)EOS中账户、钱包和密钥的关系
  • (转)Oracle存储过程编写经验和优化措施
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • .NET : 在VS2008中计算代码度量值
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .Net CoreRabbitMQ消息存储可靠机制
  • .Net Remoting(分离服务程序实现) - Part.3
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • .sys文件乱码_python vscode输出乱码
  • @for /l %i in (1,1,10) do md %i 批处理自动建立目录
  • @RequestBody与@ModelAttribute
  • [ C++ ] STL priority_queue(优先级队列)使用及其底层模拟实现,容器适配器,deque(双端队列)原理了解
  • [ 渗透测试面试篇 ] 渗透测试面试题大集合(详解)(十)RCE (远程代码/命令执行漏洞)相关面试题
  • [] 与 [[]], -gt 与 > 的比较