类和对象(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.类的引入

类和结构体的区别:

  1. 类里可以有数据:成员变量
  2. 类可以定义函数
  3. 可以写成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++访问限定符有三种:公有保护和私有,现阶段保护和私有没有区别。共有及在类外可以直接访问。保护和私有在类里可以访问,类外不可访问。

公有保护私有
publicprotectprivate
  1. 访问限定符不会限定在类里面的访问,锁外面的人不锁里面的人。
  2. 类里面可以有多个访问限定符,限定从该访问限定符到下一个访问限定符出现时位置,如果没有下一个访问限定符则到}结束。
  3. class的默认访问限定符是私有,struct是公有(因为struct要兼容C)。所以上一文中报错了。
    实际生活中不希望默认,希望大家指清楚到底是私有还是公有。
    注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别。
#pragma once
#include <string.h>
#include <stdlib.h>
struct Stack
{
publicvoid Init(int n = 4);void Push(int x);
privateint* 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结构体内存对齐规则

  1. 第一个成员在于结构体偏移量为0的地址处
  2. 其他成员变量要对齐到某个数字(对其书)的整倍的地址处
    注意:对齐数=编译器默认的一个对齐数与该成员大小的较小值。VS默认对齐数为8.
  3. 结构体的总大小:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
  4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

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;
//一般不会这么写
  1. 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()。

  1. 受到类域的限制,一般都不在类域里面去找,只在全局去找。在全局找func找不到
  2. 告诉func是Date的成员函数,调用成员函数要传递this指针,所以没有解引用,但是ptr传递给了this指针(cout<<this<<endl;),所以this指针是一个空,但不会报错,只有发生了恶劣的行为才会报错。
  3. 会不会解引用,取决于要不要在对象中去找,而不是有没有这个符号。
    调用函数一共就需要两个动作,一个是传参,传this指针,一个是调用函数,这两个动作都不涉及要去解引用。
    成员函数不是成员对象。

封装(补充)

C语言和C++真正的区别:数据结构的实现与语言无关

CC++
数据和方法分离的都封装在类里面
名字繁琐简洁
数据访问自由不受限制控制访问方式。愿意给你访问的公有,不愿意私有
底层一样

封装在一起才能通过访问限定符限制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/130804.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python】爬虫基础

爬虫是一种模拟浏览器实现&#xff0c;用以抓取网站信息的程序或者脚本。常见的爬虫有三大类&#xff1a; 通用式爬虫&#xff1a;通用式爬虫用以爬取一整个网页的信息。 聚焦式爬虫&#xff1a;聚焦式爬虫可以在通用式爬虫爬取到的一整个网页的信息基础上只选取一部分所需的…

关于运行franka_ros包中的franka_gazebo报错VMware: vmw_ioctl_command error 无效的参数.

参考的博文&#xff0c;感谢&#xff0c;解决Vmware下虚拟机下打开gazebo报错 &#xff0c;VMware: vmw_ioctl_command error 无效的参数. 首先第一个VMware: vmw_ioctl_command error 无效的参数的问题。这应该是虚拟机的bug&#xff0c;毕竟使用虚拟机和真实的物理机上是有差…

Error from server (NotFound): pods “nginx-57d84f57dc-b866m“ not found

原因&#xff1a;机房断电&#xff0c;导致服务重启 [rootmaster1 logs]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-57d84f57dc-57fkf 1/1 Running 0 75s [rootmaster1 logs]# kubectl logs -f nginx-5…

CPU-主存储器-副存储器-RAM-ROM-内存-运存-外存-硬盘-闪存-GPU-显存——关于这一系列概念的理解

文章目录 概念梳理CPU主存储器/内存/RAM/运存ROM副存储器/外存硬盘&#xff08;电脑&#xff09;、闪存&#xff08;手机&#xff09;GPU显存 可参考的手机内部结构示意图 做计算机组成原理上的题的时候&#xff0c;发觉自己对RAM和ROM的概念理解有所缺失&#xff0c;在看完一些…

QT Pyside2 Designer 的基本使用

文章目录 前言PySide2PySide2 Designer 一、安装PySide2、PyQt5二、使用designer.exe2.1 工具的大致介绍2.2 创建一个新的UI2.3 UI文件另存为/保存(CtrlS)2.4 使用python操作UI文件 总结 前言 PySide2 QT PySide2 是一个用于 Python 编程语言的开源框架&#xff0c;它提供了与…

Faster Rcnn

一、公用特征Feature Maps的获取 二、Region Proposal Network Feature Maps[bs,1024,38,38]经过3*3卷积&#xff0c;然后分别经过两个1*1的卷积&#xff0c;通道数分别为18&#xff0c;36 18 9*2 代表每个位置9个先验框为背景和目标的概率 36 9*4 代表每个位置9个先验框的…

pinduoduo(商品详情)API接口

为了进行电商平台 的API开发&#xff0c;首先我们需要做下面几件事情。 1&#xff09;开发者注册一个账号 2&#xff09;然后为每个pinduoduo应用注册一个应用程序键&#xff08;App Key) 。 3&#xff09;下载pinduoduo API的SDK并掌握基本的API基础知识和调用 4&#xff…

【Terraform】Terraform自动创建云服务器脚本

Terraform 是由 HashiCorp 创建的开源“基础架构即代码”工具 &#xff08;IaC&#xff09; 使用HCL&#xff08;配置语言&#xff09;描述云平台基础设施&#xff08;这里教你使用低级基础设施&#xff1a;交换机、云服务器、VPC、带宽&#xff09; Terraform提供者&#xf…

数据结构和算法(5):二叉树

树 向量允许通过下标或秩&#xff0c;在常数的时间内找到目标对象&#xff1b;然而&#xff0c;一旦需要对这类结构进行修改&#xff0c;那么无论是插入还是删除&#xff0c;都需要耗费线性的时间。 列表允许借助引用或位置对象&#xff0c;在常数的时间内插入或删除元素&…

Springboot整合JWT完成验证登录

目录 一、引入依赖二、JwtUtil 代码解读三、LoginController 代码解读四、整体代码五、结果展示 一、引入依赖 <dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></depende…

el-table 实现表、表格行、表格列合并

最近写vue开发项目的时候&#xff0c;很多地方用到了Element组件中的Table 表格。经过一周的边学边做&#xff0c;我总结了以下三种有关表格的合并方法。 一、合并表头 话不多说&#xff0c;先看效果图 代码如下&#xff1a; 表格结构如上&#xff0c;其中:header-cell-style对…

233062C++QTday5

实现一个图形类&#xff08;Shape&#xff09;&#xff0c;包含受保护成员属性&#xff1a;周长、面积&#xff0c; 公共成员函数&#xff1a;特殊成员函数书写 定义一个圆形类&#xff08;Circle&#xff09;&#xff0c;继承自图形类&#xff0c;包含私有属性&#xff1a;半…

自动化测试框架unittest与pytest的区别!

引言   前面文章已经介绍了python单元测试框架&#xff0c;大家平时经常使用的是unittest&#xff0c;因为它比较基础&#xff0c;并且可以进行二次开发&#xff0c;如果你的开发水平很高&#xff0c;集成开发自动化测试平台也是可以的。而这篇文章主要讲unittest与pytest的区…

QQ 逻辑漏洞可执行文件 漏洞复现

本文由掌控安全学院- wax 投稿 首先拿到QQ的版本&#xff0c;目前可测试版本包括QQ最新版本&#xff0c;TIM最新版本 新创建一个bat文件&#xff08;这个可以随意&#xff0c;上马的也可以&#xff0c;exe也可以&#xff09; &#xff0c;本次测试内容如下首先向你的手机端发一…

对接西部数据Western Digital EDI 系统

近期我们为国内某知名电子产品企业提供EDI解决方案&#xff0c;采用知行之桥 EDI 系统作为核心组件&#xff0c;成功与西部数据Western Digital&#xff08;简称西数&#xff09;建立EDI连接&#xff0c;实现数据安全且自动化传输。 EDI实施需求 EDI连接 传输协议&#xff1a;A…

数据结构 排序

目录 第八章 排序8.1排序的基本概念1. 概念2. 排序算法的分类 8.2 插入排序8.2.1 直接插入排序8.2.2 算法效率分析8.2.2 折半插入排序总结8.2.3 希尔排序 8.3 交换排序8.3.1冒泡排序8.3.2快速排序&#xff08;了解栈的过程&#xff09; 8.4 选择排序8.4.1 简单选择排序8.4.2 堆…

小工具之视频抽帧

视频抽帧工具&#xff0c;所有视频所在目录以及抽帧图片保存路径 单个视频抽帧操作步骤&#xff1a; 选择文件路径->选择保存路径->拖动跳帧间隔->点击抽取帧 批量视频抽帧操作步骤&#xff1a; 选择文件夹路径->选择保存路径->拖动跳帧间隔->点击抽取帧 imp…

iview label-in-value 和 @on-change 的使用

在select加上label-in-value 之后&#xff0c;就可以调用通过on-change默认的方法&#xff0c;获取到value和label的值了 <Select v-model"params.area" placeholder"选择区县" label-in-value clearable style"width: 102px"><Option…

pip和conda的环境管理,二者到底应该如何使用

关于pip与conda是否能混用的问题&#xff0c;Anaconda官方早就给出了回答 先说结论&#xff0c;如果conda和pip在相同环境下掺杂使用&#xff0c;尤其是频繁使用这两个工具进行包的安装&#xff0c;可能会导致环境状态混乱 就像其他包管理器一样&#xff0c;大部分这些问题均…

mysql在ubuntu上命令行登陆密码不正确

1.登陆提示如下 2.使用mysql -u root -p登录也是类似的 3.打开宝塔面板 点击root密码&#xff0c;更改密码后即可在命令行界面登录 4.登录效果如下