C++初阶--类与对象(1)

文章目录

  • 类的引入
  • 类的定义
  • 访问限定符
  • 类成员的注意事项
    • 变量名的冲突
  • 类的实例化
  • 类成员的声明与定义
  • 类的大小
  • this指针
    • 特性
  • 总结

类的引入

在c语言中,我们会这样写一个栈:

struct Stack
{int* a;int top;int capacity;
};void StackInit(struct Stack* ps);
void StackPush(struct Stack* ps, int x);

先写出一个栈的结构体出来,然后写出有关栈的函数出来;我们会把对于栈的操作部分拆分出来,所以我们说C语言是面向过程的

而在C++中,对于结构体来说,还可以把函数也写进结构体中
并且对于结构体变量类型,可以省略struct

#include<stdlib.h>
struct Stack
{int* a;int top;int capacity;void Init(){a = (int*)malloc(sizeof(int)*4);top = 0;capacity = 4;}void Push(int x){//空则扩容if (top == capacity){int newcapacity =  capacity * 2;int* New = (int*)realloc(a, sizeof(int) * (newcapacity));if (New == nullptr){perror("Newsapce Fail");exit(-1);}a = New;capacity = newcapacity;}//插入a[top] = x;top++;}
};int main()
{Stack s1;s1.Init();s1.Push(5);}

上面的这种struct的定义,C++更喜欢使用class来代替

类的定义

class Student
{};

class是定义一个类的关键字,Student是类的名字,括号内是类的主体;大体与struct是相似的;
在主体部分,类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数

class Stack
{
private:int* a;int top;int capacity;
public:void Init(){a = nullptr;top = 0;capacity = 4;}void Push(int x){//空则扩容//...//插入a[top] = x;top++;}
};

private和public是访问限定符

对于类定义的写法,一般有两种,第一种的像上面的一样,将成员函数的内容直接在类中写出,另一种就是将成员函数声明放在类中,函数的定义写在另一个文件中。
在这里插入图片描述

注意:第一种方法中,将函数直接在类中定义,会把函数的内容直接在类中展开,也就是说,直接在类中定义的话相当于是一个内联函数,所以如果函数内容较长时,还是建议写第二种方法;

访问限定符

在这里插入图片描述
C++通过访问限定符,用来控制不同代码块之间的访问权限,它们决定了类中的成员是否可以被访问和使用。

public:被public修饰的成员可以被任意代码块进行访问。

protected:被protected修饰的成员可以被当前类、同一包类、以及之类进行访问。
private:被pricate修饰的成员只能被当前类内部的其他成员所访问。

访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止

访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别

这也就可以解释class和struct的区别:
C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类默认访问权限是private
所以我们会在class类中写清楚private和pubilc。

类成员的注意事项

变量名的冲突

class Date
{
private://声明int _year;int _month;int _day;
public:void Init(int year, int month, int day){/*year = year;month = month;day = day;*///错误的,变量名冲突_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}};

在定义成员变量名的时候,需要注意成员变量名是否冲突,因为它们都在一个作用域中,所以在这里建议对于成员变量名最好多加一个符号来表示这是成员变量的,用来区分变量名。

类的实例化

类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它;

int main()
{Date d1;Date d2;//....
}

上面的d1,d2我们称之为类的对象。
一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量

类成员的声明与定义

struct Stack
{int* a;int top;int capacity;
};
int main()
{Stack s1;s1.capacity = 10;//正确的Date d1;d1._year=10;//错误的
}

在上面的限定符已经讲过,Date的成员变量都是private中的,无法在作用域外进行访问。而Stack是struct定义的,所以允许我们进行访问。但这里要注意的是Date中的成员变量,实际上只是声明而已,实际上的定义是在创建对象时定义的。

我们可以这样试验:
在这里插入图片描述
在public限定符中写一个成员变量,
在这里插入图片描述
它是可以在作用域外被使用的,因为它是公有的;

而我们定义多个对象时,
在这里插入图片描述
它们也可以打印出对应的内容。
这就说明了对于类的成员变量来说,在类中都只是声明而已,无论在private还是public,那只是限定符而已。定义都必须要在对象中进行,这样在多个对象中进行访问才不会产生冲突

而对于成员函数来说,无论你是在类中定义,还是类外定义,你都会有一个函数地址,存在多个对象时,只需要调取你的地址,在栈区中建立栈帧即可。

所以我们可以总结:类的成员变量的定义均在对象中,而类的成员函数,不用在对象中进行定义

在这里插入图片描述

类的大小

class Date
{
private://声明int _year;int _month;int _day;
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}};
class SizeNuLL
{};
class Size1NULL
{class Size2NULL{};
};
int main()
{cout << sizeof(d1) << endl;//12SizeNuLL s1;cout << sizeof(s1) << endl;//1Size1NULL s2;cout << sizeof(s2) << endl;//1无成员变量的类,对象大小开一个字节,这个字节不存储有效位用来标识的对象存在过
}

这里的计算只计算成员变量,计算方式与结构体的计算方式是一样的,会利用到内存对齐的规则。
而对于无成员变量的类来说,对象大小开一个字节,这个字节不存储有效位,用来标识的对象存在过。

this指针

class Date
{
private://声明int _year;int _month;int _day;
public:int dd;void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}};
int main()
{Date d1;d1.Init(2023, 10, 19);d1.Print();Date d2;d2.Init(2022, 9, 8);d2.Print();
}

在这里插入图片描述
上述代码中:成员函数的参数中我们没有引用相关对象的参数,对于不同对象中,它是怎么识别的呢?
C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编
译器自动完成。
在这里插入图片描述

当指针为空时:

Date* d3 = nullptr;//错误的,对象指针为空,this指针也为空d3->Init(2023, 10, 20);d3->Print();Date* d4;//错误的,d4没有初始化,指针相当于指向空d4->Init(2023, 10, 21);d4->Print();

特性

  1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。
    在这里插入图片描述

  2. 只能在“成员函数”的内部使用

在这里插入图片描述3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递
5. this指针存储的是当前被调用的成员函数对应的对象的地址,也就是在栈帧中。(一些编辑器会存储在寄存器中,如VS2022)

总结

类的成员变量实际上只是声明,定义会在变量中定义(当创建了一个类对象时);成员函数不在类对象里面,它属于公共部分,也就是每个类对象都可以调用它; 指针没有初始化和指向空,实质上都是没有指向一个存在的类对象,这样就导致指针不明确;在成员函数里面会有一个隐藏的this指针,用来表示指向成员变量,我们在编写代码不能显示this该步骤已经由编译器自动写好了,在成员函数中就可以直接调用变量;这也就说明指针为空的情况下,this指针找不到已有的成员变量;

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

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

相关文章

线性代数2:梯队矩阵形式

图片来自 Europeana on Unsplash 一、前言 欢迎阅读的系列文章的第二篇文章&#xff0c;内容是线性代数的基础知识&#xff0c;线性代数是机器学习背后的基础数学。在我之前的文章中&#xff0c;我介绍了线性方程和系统、矩阵符号和行缩减运算。本文将介绍梯队矩阵形式&#xf…

Android 如何在Service中使用ViewModel

需求&#xff1a;最近有反馈说&#xff0c;需要在service中使用网络请求&#xff0c;而我网络请求就是封装的ViewModel。然后我就发现&#xff0c;原来service不支持&#xff0c;懵了呀&#xff01;哈哈 还是去看看ViewModel的源码了解下吧。下面有几个介绍的。就不多做赘述了。…

微信小程序开发之后台数据交互及wxs应用

目录 一、后端准备 1. 应用配置 2. 数据源配置 二、数据库 1. 创建 2. 数据表 3. 数据测试 三、前端 1. 请求方法整合 2. 数据请求 3. WXS的使用 4. 样式美化 5. 页面 一、后端准备 通过SpringMVC及mybatis的技术学习&#xff0c;还有前后端分离的技术应用&…

Mycat2 分布式数据库中间件

一.安装部署 Mycat2目前还不支持直接获取Docker镜像&#xff0c;需要自己通过Dockerfile打包镜像&#xff0c;其实这也是为了开发者考虑&#xff0c;比如一些个性化功能&#xff0c;如自定义分片等 Dockerfile FROM docker.io/adoptopenjdk/openjdk8:latestENV AUTO_RUN_DIR…

RemObjects Elements 12.0 Crack

Elements 是一个现代多功能软件开发工具链。 它支持六种流行的编程语言&#xff1a;Oxygene (Object Pascal)、C#、Java、Mercury (Visual Basic.NET™)、Go 和 Swift&#xff0c;适用于所有现代平台。 使用 Elements&#xff0c;您可以为您喜欢的任何平台进行编程- 无论是单…

想要精通算法和SQL的成长之路 - 找到最终的安全状态

想要精通算法和SQL的成长之路 - 找到最终的安全状态 前言一. 找到最终的安全状态1.1 初始化邻接图1.2 构建反向邻接图1.3 BFS遍历1.4 完整代码 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 找到最终的安全状态 原题链接 我们从题目中可以看出来&#xff1a; 出度为0的…

面试官:如何理解CDN?说说实现原理?

一、是什么 CDN (全称 Content Delivery Network)&#xff0c;即内容分发网络 构建在现有网络基础之上的智能虚拟网络&#xff0c;依靠部署在各地的边缘服务器&#xff0c;通过中心平台的负载均衡、内容分发、调度等功能模块&#xff0c;使用户就近获取所需内容&#xff0c;降…

大模型技术实践(五)|支持千亿参数模型训练的分布式并行框架

在上一期的大模型技术实践中&#xff0c;我们介绍了增加式方法、选择式方法和重新参数化式方法三种主流的参数高效微调技术&#xff08;PEFT&#xff09;。微调模型可以让模型更适合于我们当前的下游任务&#xff0c;但当模型过大或数据集规模很大时&#xff0c;单个加速器&…

OpenCV中world模块介绍

OpenCV中有很多模块&#xff0c;模块间保持最小的依赖关系&#xff0c;用户可以根据自己的实际需要链接相关的库&#xff0c;而不需链接所有的库&#xff0c;这样在最终交付应用程序时可以减少总库的大小。但如果需要依赖OpenCV的库太多,有时会带来不方便&#xff0c;此时可以使…

忆联分布式数据库存储解决方案,助力MySQL实现高性能、低时延

据艾瑞咨询研究院《2022 年中国数据库研究报告》显示&#xff0c;截止2021年&#xff0c;中国分布式数据库占比达到 20%左右&#xff0c;主要以 MySQL 和 PostgreSQL 为代表的开源数据库为主。MySQL 作为备受欢迎的开源数据库&#xff0c;当前已广泛应用于互联网、金融、交通、…

【C++初阶】类和对象(上)

个人主页点击直达&#xff1a;小白不是程序媛 我的代码仓库&#xff1a;Gitee C系列专栏&#xff1a;C头疼记 目录 前言 面向过程和面向对象的初步认识 类的引入 类的定义 类的两种定义方式&#xff1a; 类的访问限定符及封装 封装 类的作用域 类的实例化 类对象模型…

LVS负载均衡集群 (NAT模式)

LVS集群 集群的概念&#xff1a; 为解决某个特定的问题&#xff0c;将多个计算机组合起来形成一个单个系统 集群的水平扩展&#xff1a; 增加设备&#xff0c;并行运行多个服务&#xff0c;通过网路连接和算法来调度服务分配的问题 集群的类型&#xff1a; 负载均衡集群&#…

【Javascript】基础数据类型

目录 基础数据类型 1.number 字面量声明 数字对象方式声明 整数判断 指定返回小数位数 NaN-表示非数字值 浮点精度 解决误差 String 字面量声明 数字对象声明 连接运算符 获取长度 大小写转换 转换成大写 转换成小写 ​编辑 移除空白 获取单字符 ​编辑 截…

html中公用css、js提取、使用

前言 开发中&#xff0c;页面会有引用相同的css、js的情况&#xff0c;如需更改则每个页面都需要调整&#xff0c;重复性工作较多&#xff0c;另外在更改内容之后上传至服务器中会有缓存问题&#xff0c;特针对该情况对公用css、js进行了提取并对引用时增加了版本号 一、提取…

分布式Trace:横跨几十个分布式组件的慢请求要如何排查?

目录 前言 一、问题的出现&#xff1f; 二、一体化架构中的慢请求排查如何做 三、分布式 Trace原理 四、如何来做分布式 Trace 前言 在分布式服务架构下&#xff0c;一个 Web 请求从网关流入&#xff0c;有可能会调用多个服务对请求进行处理&#xff0c;拿到最终结果。这个…

Redis-Sentinel高可用架构学习

Redis-Sentinel高可用架构 Redis主从复制过程&#xff1a; 主从同步原理 Redis Sentinel&#xff08;哨兵&#xff09;高可用集群方案&#xff1a;Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案。 当用Redis做Master-slave的高可用方案时&#xff0c;假如master宕机了…

Rust-后端服务调试入坑记

这篇文章收录于Rust 实战专栏。这个专栏中的相关代码来自于我开发的笔记系统。它启动于是2023年的9月14日。相关技术栈目前包括&#xff1a;Rust&#xff0c;Javascript。关注我&#xff0c;我会通过这个项目的开发给大家带来相关实战技术的分享。 如果你关注过我的Rust 实战里…

Unity⭐️Win和Mac安卓打包环境配置

文章目录 🟥 配置Android SDK1️⃣ 配置 SDK Platforms2️⃣ 配置 SDK Tools🎁 Android SDK Build-Tools🎁 Android SDK Command-line Tools(latest)🎁 Android SDK Tools(Obsolete)🟧 配置NDK🟩 配置JDK前情提示: 此方法适用于Windows/Mac 在配置时注意开启 🪜 …

解决osg绘制场景时因Z冲突导致重影或闪烁等不正常情况

目录 1. 问题的提出 2. Z冲突&#xff08;z-fighting&#xff09;简介 2.1. Z冲突&#xff08;z-fighting&#xff09;产生的原因 2.2. 如何消除Z冲突&#xff08;z-fighting&#xff09; 3. 代码实现 1. 问题的提出 今天绘制了一个棋盘格&#xff0c;鼠标在棋盘格上单击…

CVE-2019-0708漏洞实战

使用命令&#xff1a;search 0708搜索exp脚本 搜索网段中主机漏洞 use auxiliary/scanner/rdp/cve_2019_0708_bluekeep 照例&#xff0c;show options 看一下配置 设置网段set RHOSTS x.x.x.x run运行就行了 使用攻击模块 use exploit/windows/rdp/cve_2019_0708_bluekee…