类和对象(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目标检测。 代码在…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...