C++类与对象(上)【详析】

news2024/11/18 23:33:35

目录

    • 1.面向过程和面向对象初步认识
    • 2.类的引入
    • 3.类的定义
    • 4.类的访问限定符及封装
      • 4.1访问限定符
      • 4.2封装
    • 5.类的作用域
    • 6.类的实例化
    • 7.类对象模型
      • 7.1 如何计算类对象的大小
    • 8.this关键字

如果说我们对C++的初步认识,是觉得C++是对C语言不足之处的进行修补,在认识完类与对象后,我们会对C++产生新的认识

1.面向过程和面向对象初步认识

C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题;

C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成;

2.类的引入

C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。 比如: 之前在数据结构初阶中,用C语言方式实现的栈,结构体中只能定义变量;现在以C++方式实现, 会发现struct中也可以定义函数

对于C++中的struct:属性(成员变量)+方法(函数)

①兼容C中struct中的所有用法

②升级成了类

举例如下:

typedef int DataType;
//Stack为类名
struct Stack
{	
    //①属性
    DataType *_array;
    size_t _capacity;
    size_t _size;
    
    //②方法
    void Init(size_t capacity)
    {
  		//...
    }

    void Push(const DataType &data)
    {
        //...
    }

    void Destroy()
    {
        //...
    }
};

int main()
{	
    //s是对象
    Stack s;
    //【对象.方法】、【对象.属性】
    s.Init(10);
    s.Push(1);
    s.Push(2);
    s.Push(3);
    cout << s.Top() << endl;
    s.Destroy();
    return 0;
}

一般的,在定义成员变量名时,常常在前面加上前杠,例如:

class Date
{
    public:
    int _year;
    int _month;
    int _year;
    
    public:
    void Init(){
        //...
    }
}

3.类的定义

1.定义

class className
{
	// 类体:由成员函数和成员变量组成
};  // 一定要注意后面的分号

class为定义类的关键字, ClassName为类的名字, **{}**中为类的主体,注意类定义结束时后面分号不能省略

类的两种定义方式:

①声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理

class People {
public:
	int age;
	int sex;
	int height;

public:
	void Eat() {
		cout << "people can eat" << endl;
	}
	void Run() {
		cout << "people can run" << endl;
	}
};

②类声明放在.h文件中,成员函数定义放在.cpp文件中,注意: 成员函数名前需要加类名

为什么要声明和定义分离?

加强代码的可阅读性!

在cpp文件种对成员函数进行声明,注意标识,该函数的类域(即类名)

2.对象

和结构体一样,类的定义是一个类型,要访问它的成员(属性、方法)就要实例化对象

一个类可以定义多个对象

4.类的访问限定符及封装

4.1访问限定符

image-20221204115808982

① public修饰的成员在类外可以直接被访问

② protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)

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

④如果后面没有访问限定符,作用域就到 } 即类结束

class的默认访问权限为private ,struct默认为public(因为struct要兼容C)

4.2封装

面向对象的三大特性: 封装、继承、多态

在类和对象阶段,主要是研究类的封装特性,那什么是封装呢?

封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互

因此我们将属性置为private,通过public方法(公有成员)来实现对属性的操作

因此,封装的目的不是为了阻止对数据的访问,而是规定一种规范的方法,让我们对其访问

5.类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中 ;在类体外定义成员时,需要使用**:😗*作用域操作符指明成员属于哪个类域

class Person
{
public:
	void PrintPersonInfo();
private:
	char _name[20];
	char _gender[3];
	int  _age;
};

// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo()
{
	cout << _name << " " << _gender << " " << _age << endl;
}

6.类的实例化

常见错误:

Person::_age=1;                   //wrong
Person::PrintPersonInfo();        //wrong

正确的:

//通过对象
Person p1;
p1._age=10;
p1.PrintPersonInfo();
//通过指针
Person p2;
Person* ptr=&p2;
ptr->_age=20;

7.类对象模型

7.1 如何计算类对象的大小

引入:

class A
{
public:
	void PrintA()
	{
		cout << _a << endl;
	}
private:
	char _a;
};

这里类A的大小是多少呢?

结果是1,我们发现类存储时只存了变量(属性)

而类对象的大小规则,同结构体内存对齐规则

【补充】:结构体内存对齐规则

1.第一个成员在与结构体偏移量为0的地址处

2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处

注意:对齐数 = 编译器默认的一个对齐数与该成员大小的较小值,VS中默认的对齐数为8

3.结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。

4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

①例:内存对齐的体现

②例:空类大小为1——占位,不存储有效数据,标识对象存在

8.this关键字

1.引入:

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

对于上述类,有这样的一个问题:

Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?

C++中通过引入this指针解决该问题,即: C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象)

即:

void Print(Date* this) 
{
	cout << this->_year << " " << this->_month << " " << this->_day << endl;
}

注意:this指针的定义和传递是由编译器完成,我们不能去做,但是我们可以在类里面用this指针

这里的this代表d1和d2对象的地址:

image-20221213172915934

this指针与const修饰问题:

const Date* p1;      //修饰的是指针指向的对象       *p1
Date const* p2;      //修饰的是指针指向的对象       *p2
Date* const p3;      //修饰的是本身                p3

image-20230128135716151

2.this指针存在哪?

this是一个形参,一般存在栈帧中(vs下进行了优化,使用了ecx寄存器传递)

3.this指针可以为空吗?

// 1.下面程序编译运行结果是?   A、编译报错  B、运行崩溃  C、正常运行
class A
{
public:
    void Print()
    {
        cout << "Print()" << endl;
    }

private:
    int _a;
};

int main()
{
    A *p = nullptr;      //p这里是一个空指针
    p->Print();          //不发生解引用,因为成员函数的地址不在对象中,在公共代码区域
    return 0;
}
//正常运行
// 2.下面程序编译运行结果是?   A、编译报错  B、运行崩溃  C、正常运行
class A
{
public:
    void PrintA()
    {
        cout << _a << endl;    //本质是this->_a
    }

private:
    int _a;
};

int main()
{
    A *p = nullptr;            //发生空指针的解引用
    p->PrintA();
    return 0;
}
//运行崩溃

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue-router 3.x 版本中路由守卫钩子函数解析

目录概念&#xff1a;分类全局前置守卫 &#xff08; router.beforeEach &#xff09;全局解析守卫 &#xff08; router.beforeResolve &#xff09;全局后置守卫 &#xff08; router.afterEach &#xff09;路由独享守卫 &#xff08; beforeEnter &#xff09;组件内的守卫…

有哪些办法可以降低 Redis 的内存使用情况

在逛知乎时&#xff0c;看到这样一个问题&#xff0c;觉得挺不错的&#xff0c;将自己个人的见解分享给大家。问题是:有哪些办法可以降低 Redis 的内存使用情况&#xff1f;个人也对Redis做了一个比较全面的问题汇总&#xff0c;希望对大家有所帮助。Redis面试题汇总要降低内存…

Git同时配置Github和Gitlab

电脑的git需要同时管理Github上自己的代码仓库和Gitlab的公司的代码仓库&#xff0c;所以记录同时配置两者的步骤。 第一步、清除已有的全局配置&#xff08;我之前只有github的配置&#xff09; git config --global --unset user.name git config --global --unset user.em…

【论文阅读总结】Mask R-CNN翻译总结

Mask R-CNN1.摘要Mask R-CNN相关介绍与优点2.引言3.文献综述3.1 R-CNN3.2 Instance Segmentation【实例分割】4. Mask R-CNN介绍4.1 Faster R-CNN(相关细节请看相关文章)4.2 Mask R-CNN4.3 Mask Representation【遮罩表示法】4.4 RoIAlign【感兴趣区域对齐】4.4.1 RoIPool【感兴…

软件测试面试问答

笔试 笔试的话我们需要揣测具体会考什么内容&#xff0c;我们可以通过招聘信息去了解该公司需要什么样的技能&#xff0c;以此来准备笔试。一般必考的内容会有编程&#xff0c;测试用例设计&#xff0c;工作流程&#xff0c;逻辑思维等内容&#xff0c;除此之外每个公司可能还会…

【设计模式】我终于读懂了模板方法模式。。。

&#x1f34e;豆浆制作问题 编写制作豆浆的程序&#xff0c;说明如下: 1.制作豆浆的流程 选材—>添加配料—>浸泡—>放到豆浆机打碎 2)通过添加不同的配料&#xff0c;可以制作出不同口味的豆浆 3)选材、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样…

二、IA-32系列处理器 通用寄存器介绍

IA-32系列处理器 通用寄存器介绍 寄存器处理器内的特殊存储单元处理器内有多种不同用途的寄存器寄存器分别有各自的名称,以便表示及访问通用寄存器IA-32系列CPU有8个32位的通用寄存器(General-Purpose Registers)通用寄存器不仅能存储数据,而且能参与算术逻辑运算,还能给出…

OpenCV 图像轮廓检测

本文是OpenCV图像视觉入门之路的第15篇文章&#xff0c;本文详细的介绍了图像轮廓检测的各种操作&#xff0c;例如&#xff1a;轮廓检索模式、轮廓逼近算子等操作。 图像轮廓是具有相同颜色或灰度的连续点的曲线&#xff0c;轮廓在形状分析和物体的检测和识别中很有用。图像轮廓…

预训练BERT

与PTB数据集相比&#xff0c;WikiText-2数据集保留了原来的标点符号、大小写和数字&#xff0c;并且比PTB数据集大了两倍多。 我们可以任意访问从WikiText-2语料库中的一对句子生成的预训练&#xff08;遮蔽语言模型和下一句预测&#xff09;样本。 原始的BERT有两个版本&…

《Python机器学习》基础代码

1&#xff0c;要学习Python机器学习,第一步就是读入数据,这里我们以读入excel的数据为例,利用jupyter notebook来编码,具体教程看这个视频 推荐先上传到jupyter notebook,再用名字.xlsx来导入 Jupyter notebook导入Excel数据的两种方法介绍_哔哩哔哩_bilibili 2&#xff0c;…

MyBatis - 06 - MyBatis获取参数值的两种方式(重要)

文章目录1、回顾JDBC原生的获取参数值的方式2、MyBatis获取参数值的两种方式3、MyBatis获取参数值的五种情况情况1: Mapper接口方法的参数为单个字面量类型的参数ParameterMapper接口代码测试类代码ParameterMapper.xml配置方式1&#xff1a;${}ParameterMapper.xml配置方式2:#…

[8]云计算概念、技术与架构Thomas Erl-第九章 云管理机制|week9|10月29日

9.0引言 基于云的IT资源需要被建立、配置、维护和监控。 远程管理系统 资源管理系统 SLA管理系统 计费管理系统 这些系统通常会提供整合的API&#xff0c;并能够以个别产品、定制应用或者各种组合产品套装和多功能应用的形式提供给用户。 9.1 远程管理系统 远程管理系统…

「回顾RKDC2023」飞凌嵌入式受邀亮相第七届瑞芯微开发者大会

2023年2月23-24日&#xff0c;第七届瑞芯微开发者大会&#xff08;RKDC2023&#xff09;在福州隆重举行&#xff0c;飞凌嵌入式作为瑞芯微生态合作伙伴受邀参会&#xff0c;并与数千名开发者科技公司代表及行业领袖共同聚焦行业新兴产品需求&#xff0c;探讨新硬件发展趋势&…

webpack实战,手写loader和plugin

序言 对于 webpack 来说&#xff0c; loader 和 plugin 可以算是需求程度最为广泛的配置项了。但是呢&#xff0c;单单止步于配置可能还不够。如果我们自己有时候想要 diy 一个需求&#xff0c;但是 webpack 又没有相关的 loader 和 plugin 。那这个时候我们可能就得开始造点轮…

【JAVA程序设计】(C00105)基于SSM大学在校生职业走向调查分析系统-有文档

基于SSM大学在校生职业走向调查分析系统-有文档项目简介项目获取开发环境项目技术运行截图项目简介 基于ssm框架大学生在校生职业走向调查分析系统分为二个角色&#xff1a;系统管理员、用户 管理员角色包含以下功能&#xff1a; 调查课题管理、留言信息管理、在校学生管理、社…

华为OD机试题,用 Java 解【最小步骤数】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…

JavaSE-3 Java运行原理

一、Java的运行过程 &#x1f34e;Java程序运行时,必须经过编译和运行两个步骤。 首先将后缀名为.java的源文件进行编译,最终生成后缀名为.class的字节码文件。然后Java虚拟机将字节码文件进行解释执行,并将结果显示出来。具体过程如下图所示。 &#x1f349;Java程序的运行过…

Java集合学习:LinkedList源码详解

前言 LinkedList在我们平时工作中使用频率非车高&#xff0c;底层是基于双向链表数据结构实现&#xff0c;下面从经常使用的几个方法来了解其原理。 正文 结构 我们先看下LinkedList的重要属性 /**存储链表数量*/transient int size 0;/**存储链表的头节点*/transient Node…

MTK平台使用Omnipeek分析空口协议讲解

讲解这个之前,我们先来了解下beacon/robe Request/Probe Response 三种帧 beacon帧 信标帧,由AP以一定的时间间隔周期性发出,以此来告诉外界自己无线网络的存在。 Beacon帧作为802.11中一个周期性的帧,Beacon周期调高,对应睡眠周期拉长,故节能(即越来休息100ms再起来…

Laravel框架04:视图与CSRF攻击

Laravel框架04&#xff1a;视图与CSRF攻击一、视图概述二、变量分配与展示三、模板中直接使用函数四、循环与分支语法标签五、模板继承、包含1. 继承2. 包含六、外部静态文件引入七、CSRF攻击概述八、从CSRF验证中排除例外路由一、视图概述 视图存放在 resources/views 目录下…