C++ 类与对象(上)

在C++中,在原来C语言基础上引入了类的概念。与C语言最大的不同就是:C++可以在类中定义函数。由类声明的变量,称为对象

1.类的定义

1.1类定义的格式

class为定义类的关键字,Stack为类的名字,{}中为类的主体,(类定义结束时后面分号不能省略)类体中内容称为类的成员:类中的变量称为成员变量,类中的函数称为类的方法或成员函数。

class stack
{
public://成员函数void init(int n = 4){array = (int*)malloc(sizeof(int) * n);if (array == nullptr){perror("malloc申请空间失败");return;}capacity = n;top = 0;}void push(int x){top = top + 1;array[top] = x;}int top(){//assert(top > 0);return array[top - 1];}void destory(){free(array);array = nullptr;top = capacity = 0;}private://成员变量int* array;int capacity;int top;
};

为了区分成员变量,一般会习惯成员变量加上一个特殊标识,如成员前面或后面加上_或m开头。

注意C++中这个并不是强制的,只是一些惯例,具体看公司要求。

​
class Date
{
public://为了区分成员变量,一般习惯将成员变量加一个特殊标识,如_或mvoid Init(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;
};​

 

C++兼容C语言,可以利用C语言的结构体关键字struct来定义类。

C++升级struct升级成了类

1.类里可以定义函数

2.struct名称就可以代表类型

struct Date
{int a;int b;};
int main()
{Date d1;struct Date d2;//这两种表述都对,不需要再typedefreturn 0;
}

1.2访问限定符

C++用一种实现封装的方式,用类将对象的属性和方法结合在一块,让对象更加完善,通过访问权限,选择性的将其接口提供给外部的用户使用

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

2.protectedprivate修饰的成员在类外不能被直接访问

3.访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,如果后面没有访问限定符,作用域就到}结束

4.class定义成员没有被访问限定符修饰时默认为private,struct默认为public

5.一般成员变量都会被限制为private/protected,需要给别人使用的成员函数会改为public

1.3类域

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

class Stack
{
public://成员函数void Init(int n = 4);private://成员变量int* array;int top;int capacity;};void Stack::Init(int n )//声明和定义分离,需要指定类域{array = (int*)malloc(sizeof(int) * n);if (array == nullptr){perror("malloc申请空间失败");return;}capacity = n;top = 0;
}

类域影响的是编译的查找规则,上面程序中Init如果不指定类域Stack,那么编译器就把init当成全局函数,那么编译时找不到array等成员的声明/定义在哪,就会报错。

指定类域Stack,就知道Init是成员函数。当前域找不到的array等成员,就会到类域中去查找。 

2.实例化

2.1概念

1.用类类型在物理内存中创建对象的过程,称为类实例化出对象。

2.类是对象进行一种 抽象描述,是一个模型一样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,用类实例化出对象时,才会分配空间

3.一个类可以实例化出多个对象,实例化出的对象占用实际的物理内存,存储类成员变量

class Date
{
public://为了区分成员变量,一般习惯将成员变量加一个特殊标识,如_或mvoid Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}private://这里只是声明,没有开空间int _year;int _month;int _day;
};int main()
{Date d1;//Date类 实例化出对象d1d1.Init(2025, 1, 21);d1.Print();return 0;}

2.2对象的大小

类对象中有哪些成员呢?

类实例化出的每个对象,都有独立的数据空间,所以对象中肯定包含成员变量,那么成员函数是否包含呢?

首先函数被编译后是一段指令,对象中没办法存储,这些指令存储在一个单独的区域(代码段),那么对象中非要存储的话,只能是成员函数的指针。那么,有没有存指针的必要呢?Date实例化d1和d2两个对象,它俩都有各自独立的成员变量year/month/day存储各自的数据,但是d1和d2的成员函数init和print指针确是一样的,存储在对象中就浪费了。如果实例化100个对象,那么成员函数指针存储100次就太浪费了。

注:函数指针是不需要存储的,函数指针是一个地址,调用函数被编译成汇编指令(call指令),编译器在编译链接时就要找到函数的地址,不是在运行时找。

所以分析得到对象中只存储成员变量,C++规定实例化的对象也要符合内存对齐的规则

#include<iostream>
using namespace std;class A
{
public:void Print(){cout << ch << endl;}private:char ch;int i;
};int main()
{A a;cout << sizeof(a) << endl;return 0;
}

 

我们再来研究一下空类

 

#include<iostream>
using namespace std;class B
{
public:void Print(){//}
};class C
{};int main()
{B b;C c;cout << sizeof(b) << endl;cout << sizeof(c) << endl;return 0;
}

 

为什么没有成员变量的B和C类对象的大小是1呢?

因为如果一个字节不给,怎么表示对象存在过呢!这里的1字节,纯粹是为了占位标识对象存在。 

3.this指针

首先先来看一段代码

#include<iostream>
using namespace std;class Date
{
public:void Init(int year, int month, int day){_year=year;_month=month;_day=day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}private:int _year;int _month;int _day;
};int main()
{Date d1, d2;d1.Init(2025, 1, 21);d2.Init(2025, 1, 22);d1.Print();d2.Print();return 0;
}

这段代码中,Date类中有Init和Print两个成员函数,函数体中没有关于不同对象的区分,那么当d1调用Init和Print函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?

C++中一个隐含的this指针解决这个问题。

1.编译器编译后,类的成员函数默认都会在形参第一个位置,增加一个当前类类型的指针,叫做this指针。

Date类的Init的真实原型为

void Init(Date* const this,int year,int month,int day)

2.类的成员函数中访问成员变量本质都是通过this指针访问的


_year=year;//this->_year=year

3.C++规定不能在形参和实参的位置显示的写this指针,编译时编译器会处理,但是可以在函数体内显示使用this指针

实际上的代码

d1.Init(&d1,2025,1,21)

4.两道代码题

 题目1.

下面程序的运行结果是 编译报错 运行崩溃 还是 正常运行?

#include<iostream>
using namespace std;class A
{
public:void Print(){cout << "A::Print()" << endl;}
private:int _a;
};int main()
{A* p = nullptr;p->Print();return 0;
}

答案是正常运行

对空指针解引用不是会发生运行崩溃吗?首先我们得明白,成员函数并不存放在类对象中,而是存放在公共代码段。表面上看起来是对空指针解引用,其实编译器不需要通过解引用去找对应函数,只需要去公共代码区执行对应函数即可。

空指针没有解引用就不会报错,所以答案是正常运行。

题目2.

下面程序的运行结果是 编译报错 运行崩溃 还是 正常运行?

#include<iostream>
using namespace std;class A
{
public:void Print(){cout << "A::Print()" << endl;cout << _a << endl;}
private:int _a;
};int main()
{A* p = nullptr;p->Print();return 0;
}

 

答案是运行崩溃

这里我们访问了对应的成员变量,会传递对应对象的地址,会对空指针进行解引用,所以会崩溃。

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

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

相关文章

什么样的问题适合用递归

递归是一种通过函数调用自身来解决问题的方法。递归适用于那些可以被分解为相似子问题的问题&#xff0c;即原问题可以通过解决一个或多个更小规模的同类问题来解决。递归通常需要满足以下两个条件&#xff1a; 递归基&#xff08;Base Case&#xff09;&#xff1a;问题的最简…

Qt基础项目篇——Qt版Word字处理软件

一、核心功能 本软件为多文档型程序&#xff0c;界面是标准的 Windows 主从窗口 拥有&#xff1a;主菜单、工具栏、文档显示区 和 状态栏。 所要实现的东西&#xff0c;均在下图了。 开发该软件&#xff0c;主要分为下面三个阶段 1&#xff09;界面设计开发 多窗口 MDI 程序…

【物联网】keil仿真环境设置 keilV5可以适用ARM7

文章目录 一、ARM指令模拟器环境搭建1. keil软件2. Legacy Support 二、Keil仿真环境设置1. 创建一个项目2. 编译器介绍(1)arm-none-eabi-gcc(2)arm-none-linux-gnueabi-gcc(3)arm-eabi-gcc(4)grmcc(5)aarch64-linux-gnu-gcc 3. 安装编译器(1)设置调试 一、ARM指令模拟器环境搭…

StackOrQueueOJ3:用栈实现队列

目录 题目描述思路分析开辟队列入队列出队列 代码展示 题目描述 原题&#xff1a;232. 用栈实现队列 思路分析 有了前面的用队列实现栈的基础我们不难想到这题的基本思路&#xff0c;也就是用两个栈来实现队列&#xff0c;&#xff08;栈的实现具体参考&#xff1a;栈及其接口…

二叉树--堆排序

我们之前学过冒泡排序算法&#xff0c;还有其他的排序算法之类的&#xff0c;我们今天来讲堆排序算法&#xff1b; 假设我们现在有一个数组&#xff0c;我们想要对其进行排序&#xff0c;我们可以使用冒泡排序来进行排序&#xff1b;我们也可以使用堆排序来进行排序&#xff1b…

简述mysql 主从复制原理及其工作过程,配置一主两从并验证

第一种基于binlog的主从同步 首先对主库进行配置&#xff1a; [rootopenEuler-1 ~]# vim /etc/my.cnf 启动服务 [rootopenEuler-1 ~]# systemctl enable --now mysqld 主库的配置 从库的配置 第一个从库 [rootopenEuler-1 ~]# vim /etc/my.cnf [rootopenEuler-1 ~]# sys…

【技术总结类】2024,一场关于海量数据治理以及合理建模的系列写作

目录 1.今年的创作路线 2.先说第一条线 2.1.由日志引出的海量文本数据存储和分析问题 2.2.监控以及监控的可视化 2.3.数据量级再往上走牵扯出了大数据 2.4.由大数据牵扯出的JAVA线程高级内容 3.第二条线&#xff0c;也是2025要继续的主线 1.今年的创作路线 今年的写作内…

用于牙科的多任务视频增强

Multi-task Video Enhancement for Dental Interventions 2022 miccai Abstract 微型照相机牢牢地固定在牙科手机上&#xff0c;这样牙医就可以持续地监测保守牙科手术的进展情况。但视频辅助牙科干预中的视频增强减轻了低光、噪音、模糊和相机握手等降低视觉舒适度的问题。…

Hnu电子电路实验2

目录 【说明】 与本次实验相关的代码及报告等文件见以下链接&#xff1a; 一、实验目的 二、实验内容 三&#xff1a;实验原理 1.指令译码器 2.AU 算术单元 四&#xff1a;实验过程 1.指令译码器 A&#xff09;创建工程&#xff08;选择的芯片为 familyCyclone II&am…

C语言之图像文件的属性

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 图像文件属性提取系统设计与实现 目录 设计题目设计内容系统分析总体设计详细设计程序实现…

AI 新动态:技术突破与应用拓展

目录 一.大语言模型的持续进化 二.AI 在医疗领域的深度应用 疾病诊断 药物研发 三.AI 与自动驾驶的新进展 四.AI 助力环境保护 应对气候变化 能源管理 后记 在当下科技迅猛发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;无疑是最具影响力的领域之一。AI 技…

ElasticSearch DSL查询之排序和分页

一、排序功能 1. 默认排序 在 Elasticsearch 中&#xff0c;默认情况下&#xff0c;查询结果是根据 相关度 评分&#xff08;score&#xff09;进行排序的。我们之前已经了解过&#xff0c;相关度评分是通过 Elasticsearch 根据查询条件与文档内容的匹配程度自动计算得出的。…

【NLP基础】Word2Vec 中 CBOW 指什么?

【NLP基础】Word2Vec 中 CBOW 指什么&#xff1f; 重要性&#xff1a;★★ CBOW 模型是根据上下文预测目标词的神经网络&#xff08;“目标词”是指中间的单词&#xff0c;它周围的单词是“上下文”&#xff09;。通过训练这个 CBOW 模型&#xff0c;使其能尽可能地进行正确的…

资料03:【TODOS案例】微信小程序开发bilibili

样式 抽象数据类型 页面数据绑定 事件传参

vim文本编辑器

vim命令的使用&#xff1a; [rootxxx ~]# touch aa.txt #首先创建一个文件 [rootxxx ~]# vim aa.txt #vim进入文件aa.txt进行编辑 vim是vi的升级版&#xff0c;具有以下三种基本模式&#xff1a; 输入模式(编辑模式) 点击i进入编辑模式 &#xff08;说明…

(undone) 并行计算学习 (Day2: 什么是 “伪共享” ?)

伪共享是什么&#xff1f; TODO: 这里补点文档&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 缓存一致性、同步的代价&#xff01;&#xff01;&#xff01; 也就是&#xff0c;当不同线程所访问的内存元素恰好在同一个 cache line 上时&#xf…

基于python的博客系统设计与实现

摘要&#xff1a;目前&#xff0c;对于信息的获取是十分的重要&#xff0c;我们要做到的不是裹足不前&#xff0c;而是应该主动获取和共享给所有人。博客系统就能够实现信息获取与分享的功能&#xff0c;博主在发表文章后&#xff0c;互联网上的其他用户便可以看到&#xff0c;…

使用插件SlideVerify实现滑块验证

作者gitee地址&#xff1a;https://gitee.com/monoplasty/vue-monoplasty-slide-verify 使用步骤&#xff1a; 1、安装插件 npm install --save vue-monoplasty-slide-verify 2、在main.js中进行配置 import SlideVerify from vue-monoplasty-slide-verify; Vue.use(SlideV…

【深度学习项目】语义分割-FCN网络(原理、网络架构、基于Pytorch实现FCN网络)

文章目录 介绍深度学习语义分割的关键特点主要架构和技术数据集和评价指标总结 FCN网络FCN 的特点FCN 的工作原理FCN 的变体和发展FCN 的网络结构FCN 的实现&#xff08;基于Pytorch&#xff09;1. 环境配置2. 文件结构3. 预训练权重下载地址4. 数据集&#xff0c;本例程使用的…

2024年博客之星主题创作|从零到一:我的技术成长与创作之路

2024年博客之星主题创作&#xff5c;从零到一&#xff1a;我的技术成长与创作之路 个人简介个人主页个人成就热门专栏 历程回顾初来CSDN&#xff1a;怀揣憧憬&#xff0c;开启创作之旅成长之路&#xff1a;从平凡到榜一的蜕变持续分享&#xff1a;打卡基地与成长复盘四年历程&a…