类和对象(1)
文章目录
- 1.面向过程和面向对象初步认识
- 2.类的引入
- 3.类的定义
- 4.类的访问限定符和封装
- 4.1访问限定符
- 4.2封装
- 5.类的作用域
- 6.类的实例化
- 6.2结构体内存对齐规则
- 7.this指针
- 7.2this指针的特性
- 封装(补充)
1.面向过程和面向对象初步认识
C++面向对象但不纯面向对象。JAVA纯面向对象。
所以C++支持C和C++面向对象混编。
C面向过程,关注的是过程
2.类的引入
类和结构体的区别:
- 类里可以有数据:成员变量
- 类可以定义函数
- 可以写成ListNode,不需加struct。
C struct ListNode是类型。
C
//C++兼容C结构体的用法。
typedef struct ListNode
{int val;struct ListNode* next;
}LTN;
C++
//C++把结构体升级成类
struct ListNode//声明这是个类,struct关键字不能去掉
{int val;ListNode* next;//后面想用这个类型的时候可以去掉。
};
如何用类?
C数据和方法分离,C++方法可以在类的里面
struct Stack
{
//成员函数
//成员函数直接定义到类里面void Init(int n=4)//缺省值{a = (int*)malloc(sizeof(int) * n);if (nullptr == a){perror("malloc申请空间失败");return;}capacity = n;size = 0;}void Push(int x){//...a[size++] = x;}//成员变量int* a;int size;int capacity;
};
int main()
{Stack st;//对象//如何调用函数?st.Init(4);st.Push(1);st.Push(2);st.Push(3);st.Push(4);return 0;
}
C++可以用struct定义类,但更喜欢用class定义类。
3.类的定义
class className
{//类体:包括成员函数(类的方法)和成员变量(类的属性)
};//一定要注意后面的分号!!!!
- class:定义类的关键字
- className:类名
- {}:类的主体
- 类体中的内容:类的成员
定义一个声明和定义分离的类。
缺省参数生命和定义不能同时给,一般在声明给。
Stack.h
#pragma once
#include <string.h>
#include <stdlib.h>
//类成员函数声明和定义分离
struct Stack
{//成员函数void Init(int n = 4);//缺省参数在声明给void Push(int x);//类的声明//成员变量int* a;int size;int capacity;
};
Stack.cpp
#include "Stack.h"
void Stack::Init(int n)//Stack告诉编译器Init不是全局函数,是栈这个类的成员函数
{a = (int*)malloc(sizeof(int) * n);//看栈这个类里有没有a这个成员变量if (nullptr == a){perror("malloc申请空间失败");return;}capacity = n;size = 0;
}
void Stack::Push(int x)
{//...a[size++] = x;
}
用class Stack却编不过,为什么呢?
此时要用到访问限定符。
4.类的访问限定符和封装
4.1访问限定符
C++访问限定符有三种:公有保护和私有,现阶段保护和私有没有区别。共有及在类外可以直接访问。保护和私有在类里可以访问,类外不可访问。
公有 | 保护 | 私有 |
---|---|---|
public | protect | private |
- 访问限定符不会限定在类里面的访问,锁外面的人不锁里面的人。
- 类里面可以有多个访问限定符,限定从该访问限定符到下一个访问限定符出现时位置,如果没有下一个访问限定符则到}结束。
- class的默认访问限定符是私有,struct是公有(因为struct要兼容C)。所以上一文中报错了。
实际生活中不希望默认,希望大家指清楚到底是私有还是公有。
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别。
#pragma once
#include <string.h>
#include <stdlib.h>
struct Stack
{
public:void Init(int n = 4);void Push(int x);
private:int* a;int size;int capacity;
};
大多数情况下成员变量都是私有的,成员函数不给别人用的是私有,给别人用的是公有。
C++中struct和class没有区别,但是struct可以像C语言去用。
Test.cpp
class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;};
int main()
{Stack st;Date d1;d1.Init(2023, 2, 3);//调用函数,年月日被初始化return 0;
}
4.2封装
【面试题】:面向对象的三大特性:封装,继承,多态
封装:将下面的细节藏起来,本质是一种更好的管理。
C++的封装:将数据和方法都放在类里面去了,即当前封装的极限,并把自己想访问的定义成共有,不想的定义成私有和保护。
5.类的作用域
类定义出一个新的作用域(类域)。
class Person
{public:void PrintPersonInfo();private:char _name[20];char _gender[3];int _age;
};
void Person::PrintPersonInfo()//PrintPersonInfo属于Person这个类域
{cout<<_name<<" "<<_gender<<" "<<_age<<endl;//此时可以调用私有
}
6.类的实例化
即用类类型
声明即要定义这个函数或变量,这个变量的类型是什么,名称是什么,参数是什么,但实际这个变量没有出来。定义即把其实实在在在的空间给开出来(对于变量而言)。
类就像一个别墅的设计图,设计了细节,但不能住人,实例化即根据设计图建造出一栋栋别墅。
class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}//函数的定义
private:int _year;int _month;int _day;//声明,没有开空间};
只需要计算成员变量的大小。
int main()
{//类对象实例化--开空间Date d1;//定义才是开空间,对于对象整体定义。//Date._year=1;//Date::year=0;//以上两种不可以,声明内不可存数据。//d1._year=1;//也不行,访问限定符是私有的。访问不了,访问的时候需要调用这个函数。改成公有就可以了。d1.Init(2023,9,12);//Init函数存在哪里呢?d1._year++;cout<<sizeof(d1)<<endl;//类对象大小要考虑内存对齐规则return 0;
}//输出12
为什么成员变量存在对象里面,成员函数不存在对象里面?
每个对象的成员变量不一样,需要独立存储。
每个对象调用的成员函数一样,放到共享公共区域(代码段)。
只需要计算成员变量的大小。
//类中既有成员变量,又有成员函数
class A1{
pubic:void f1(){}
private:int a;
};//sizeof(A1):4
//类中仅有成员函数
class A2{
public:void f2(){}
};//sizeof(A2):1//【考点】如果是0,A2 aa1;没有实例化,不能取地址
//类中什么也没有
class A3
{};//sizeof(A3):1,这一个字节用来进行占位,不存储有效数据,标识对象存在过,被实例化定义出来了。
没有成员变量的类都是一个字节
6.2结构体内存对齐规则
- 第一个成员在于结构体偏移量为0的地址处
- 其他成员变量要对齐到某个数字(对其书)的整倍的地址处
注意:对齐数=编译器默认的一个对齐数与该成员大小的较小值。VS默认对齐数为8. - 结构体的总大小:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
7.this指针
原来代码:
class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}
编译器处理完:
class Date
{
public:void Init(Date*this,int year, int month, int day){this->_year = year;this->_month = month;this->_day = day;}
原来代码:
int main()
{Date d1;Date d2;d1.Init(2023, 2, 3);d2.Init(2022, 2, 3);return 0;
}
编译器处理完:
int main()
{Date d1;Date d2;d1.Init(&d1,2023, 2, 3);d2.Init(&d2,2022, 2, 3);return 0;
}
如果是d1调用,this是d1的地址,赋值给d1的年月日。
不可以自己去加。
//可以在类里使用this,但是实参和形参里不可以
cout<<this<<endl;
this->_year = year;
this->_month = month;
this->_day = day;
//一般不会这么写
- this存在哪里?–存在对象里面?答案❌。
在栈上,因为他是形参,隐含的形参,不需要显示写,是编译器自己加的。/VS下通过ecx寄存器。
程序进行编译,编译后成员变量存在对象里,实例化出一个对象,对象存在栈上。成员函数不要存在栈中,因为成员函数存在一个公共区域,编译的时候要确定call这个函数的地址,这个地址不在对象中去找,在代码段。因为函数的地址是这些指令的地址,这些指令是存在哪呢?存在于代码段。两个东西完全不一样,要从两个不同的角度理解。一个是指令,一个是指令运行过程中的相关数据。不要把两个东西混在一起。
《深入理解计算机系统》——修炼内功
7.2this指针的特性
void func()
{cout<<this<<endl;cou<<"func()"<<endl;}
int main()
{
//编译报错 运行崩溃 正常运行Date* ptr=nullptr;ptr->func();//结果:正常运行ptr->Init(2023,9,12);//运行崩溃,用this去解引用了this->yearptr->_year;//会崩溃,因为_year在对象里面,到指针指向的对象去找,指针是一个空指针,相当于解引用。(*ptr).func();//正常运行,ptr真正的意义是传递给this,所以也是正常运行,没有解引用这个行为Date::func();//不能这么调用,因为要传递this指针。没有this指针调用。
}
指针调用用箭头,有箭头不一定解引用。函数不在对象里。调用这个函数要call这个地址,这个地址在公共区域去找,公共区域:代码段。
成员函数不可以不用对象去调,直接func()。
- 受到类域的限制,一般都不在类域里面去找,只在全局去找。在全局找func找不到
- 告诉func是Date的成员函数,调用成员函数要传递this指针,所以没有解引用,但是ptr传递给了this指针(cout<<this<<endl;),所以this指针是一个空,但不会报错,只有发生了恶劣的行为才会报错。
- 会不会解引用,取决于要不要在对象中去找,而不是有没有这个符号。
调用函数一共就需要两个动作,一个是传参,传this指针,一个是调用函数,这两个动作都不涉及要去解引用。
成员函数不是成员对象。
封装(补充)
C语言和C++真正的区别:数据结构的实现与语言无关
C | C++ | |
---|---|---|
数据和方法 | 分离的 | 都封装在类里面 |
名字 | 繁琐 | 简洁 |
数据访问 | 自由不受限制 | 控制访问方式。愿意给你访问的公有,不愿意私有 |
底层 | 一样 |
封装在一起才能通过访问限定符限制。
相关文章:

类和对象(1)
文章目录 1.面向过程和面向对象初步认识2.类的引入3.类的定义4.类的访问限定符和封装4.1访问限定符4.2封装 5.类的作用域6.类的实例化6.2结构体内存对齐规则 7.this指针7.2this指针的特性 封装(补充) 1.面向过程和面向对象初步认识 C面向对象但不纯面向…...

学会用命令行创建uni-app项目并用vscode开放项目
(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 创建 uni-app 项目 命令行创建 uni-app 项目 编译和运行 uni-app 项目: 用 VS Code 开发 uni…...

java.lang.ClassCastException: android.os.BinderProxy cannot be cast to ...
项目开发遇到下面这个报错了! 问题原因 直接说原因,就是因为进程间不能直接传递对象,应该传递该Binder对象的映射(代理对象),所以类型转换就出错了。如果在同一个进程中,直接传递对象没有关系&a…...
AIGC(生成式AI)试用 3 -- 专业主题
何为专业? 主要研究某种学业或从事某种事业 我的理解可能是在某个方向、某个行业,专业的更靠谱、说了更算、表达的更晰,结果更有说服力 本次提问:你我的专业 生成式AI知道你我的专业吗?生成式AI如何诠释你…...
rsyslog-日志管理 logrotate-日志轮转
日志的管理的方式,以及怎么自己写一个管理日志的小脚本,其实也不能算脚本 管理日志的进程 rsyslogd:绝大部分日志记录,和系统操作有关,安全,认证sshd,su,计划任务at,cron… httpd/nginx/mysql: …...

类和对象续
目录 包 自定义包 包的访问权限控制 常见的包 Static成员 静态成员变量 静态成员方法 代码块 构造块 静态块 重写 继承 继承是啥? 父类成员访问 子类中访问父类成员变量 两者不同名 两者同名 子类中访问父类对的成员方法 super 子类构造方法 …...

SpringCloud:Feign实现微服务之间相互请求
文章目录 🎉欢迎来到Java学习路线专栏~SpringCloud:Feign实现微服务之间相互请求 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒🍹✨博客主页:IT陈寒的博客🎈该系列文章专栏:Java学习路线📜其他专栏…...

LeetCode 1359. Count All Valid Pickup and Delivery Options【动态规划,组合数学】1722
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...

[杂谈]-从硬件角度理解二进制数
从硬件角度理解二进制数 文章目录 从硬件角度理解二进制数1、概述2、模拟电路3、数字电路4、逻辑电平5、TTL 器件的电压水平6、总结 1、概述 二进制数以 2 为基数系统表示,该系统只有两 (2) 个不同的数值,即 0 和 1。就像最常见的那样,十进制…...

Fast-DDS 服务发现简要概述
阅读本文章需要对DDS基础概念有一些了解,一些内容来自Fast-DDS官方文档,一些是工作中踩过的坑。 1. 服务发现阶段 满足OMG标准的DDS服务发现分为两部分,分别是: PDP(Participant Discovery Protocol 参与者发现协议):参与者确认…...

基于spingboot的websocket订阅、广播、多人聊天室示例
概述 基于spingboot的websocket多人聊天系统。包括订阅,广播、点对点单人聊天,多人聊天室功能。 详细 一、运行效果 简单示例 广播 单人聊天 多人聊天室 二、相关代码 websocket配置 package com.iamgpj.demowebsocket.config;import com.iamgpj.d…...

Linux mac Windows三系统 局域网文件共享方法
主要工具: Samba是一个开源的软件套件,允许Linux系统与Windows系统之间共享文件和打印机。 一、首先是Linux共享的设置 ①安装 sudo apt-get install samba ②创建共享文件夹 sudo mkdir /home/share ③配置用户 sudo smbpasswd -a kequan ④修改…...

Java——比较器
引入的背景 我们知道基本数据类型的数据(除boolean类型外)需要比较大小的话,直接使用比较运算符即可,但是引用数据类型是不能直接使用比较运算符来比较大小的。那么,如何解决这个问题呢? 在Java中经常会涉…...
【数据结构】初识泛型
文章目录 一般的类和方法,只能使用具体的类型: 要么是基本类型,要么是自定义的类。这种限制对代码的束缚就会很大。所以我们引入了泛型。泛型,泛顾名思义就是广泛的意思。就是适用于许多许多类型。从代码上讲,就是对类型实现了参数…...
代码随想录--哈希--有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 示例 1: 输入: s "anagram", t "nagaram" 输出: true 示例 2: 输入: s "rat", t "car" 输出: false 说明: 你可以假设字符串只包含小写字母。…...
MySQL——数据的增删改
2023.9.12 本章开始学习DML (数据操纵语言) 语言。相关学习笔记如下: #DML语言 /* 数据操作语言: 插入:insert 修改:update 删除:delete */#一、插入语句 #方式一:经典的插入 /* 语法: insert …...

云服务器与http服务器
如何与http服务器建立连接(客户端)? http请求设计格式: 例子: 发送http请求 http数据响应格式: 接收http服务器返回的数据需要进一步进行字符串处理操作,提取有用的数据。...

golang教程 beego框架笔记一
安装beego 安装bee工具 beego文档 # windos 推荐使用 go install github.com/beego/bee/v2master go get -u github.com/beego/bee/v2masterwindows使用安装bee工具时碰到的问题; 环境配置都没有问题,但是执行官网的命令:go get -u github…...

【深度学习】Mini-Batch梯度下降法
Mini-Batch梯度下降法 在开始Mini-Batch算法开始之前,请确保你已经掌握梯度下降的最优化算法。 在训练神经网络时,使用向量化是加速训练速度的一个重要手段,它可以避免使用显式的for循环,并且调用经过大量优化的矩阵计算函数库。…...

AI项目六:WEB端部署YOLOv5
若该文为原创文章,转载请注明原文出处。 一、介绍 最近接触网页大屏,所以就想把YOLOV5部署到WEB端,通过了解,知道了两个方法: 1、基于Flask部署YOLOv5目标检测模型。 2、基于Streamlit部署YOLOv5目标检测。 代码在…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...