初谈类和对象

在这里插入图片描述

文章目录

  • 前言
  • 类的引入
  • 类的定义
    • 类的两种定义方式
    • 成员命名规则
  • 类的访问限定符及封装
    • 访问限定符
    • 面试题
    • 封装
  • 类的作用域
  • 类的实例化
  • 类对象模型
    • 计算类对象的大小
  • this指针
    • this指针特性

前言

C语言是面向过程的,关注点是过程;而C++面向的是对象,关注的是对象,将一件事拆分成不同的,靠对象之间的交互完成。

比如你在洗衣服时,四个对象:人、洗衣机、洗衣液、衣服。这四个对象之间相互作用,完成了对衣服的清洗,而你不需要关注洗衣机如何去洗衣服、如何去甩干衣服。

类的引入

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

# define _CRT_SECURE_NO_WARNINGS
#include<iostream>using namespace std;typedef int DataType;
struct Stack
{void Init(size_t capacity){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (nullptr == _array){perror("malloc申请空间失败");return;}_capacity = capacity;_size = 0;}void Push(const DataType& data){// 扩容_array[_size] = data;++_size;}DataType Top(){return _array[_size - 1];}void Destroy(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}DataType* _array;size_t _capacity;size_t _size;
};
int main()
{Stack s;s.Init(10);s.Push(1);s.Push(2);s.Push(3);cout << s.Top() << endl;s.Destroy();return 0;
}

在C++中,struct结构体里面不仅可以声明变量,还可以定义函数。

C++中这种结构体更喜欢叫做class

类的定义

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

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

类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数

类的两种定义方式

  1. 声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
class Person
{
public:void shown(){cout << _name << "-" << _sex << "-" << _age << endl;}public:char* _name;char* _sex;int _age;
};
  1. 类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::
//learn.h文件
class Person
{
public:void shown();
public:char* _name;char* _sex;int _age;
};
//learn.c文件
void Person::shown()
{cout << _name << "-" << _sex << "-" << _age << endl;
}

一般情况下,更期望采用第二种方式。注意:上课为了方便演示使用方式一定义类,大家后序工作中尽量使用第二种。

成员命名规则

先来看看这个函数:

class Date
{
public:
void Init(int year)
{year = year;
}
private:
int year;
};

这里的year到底是成员变量,还是函数形参?

有歧义

一般建议:

class Date
{
public:
void Init(int year)
{
_year = year;
}
private:
int _year;
};
// 或者这样
class Date
{
public:
void Init(int year)
{
mYear = year;
}
private:
int mYear;
};

具体习惯基于自己

类的访问限定符及封装

访问限定符

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

在这里插入图片描述

访问限定符说明:

  1. public修饰的成员在类外可以直接被访问
  2. protectedprivate修饰的成员在类外不能直接被访问(此处protectedprivate是类似的)
  3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
  4. 如果后面没有访问限定符,作用域就到 } 即类结束。
  5. class的默认访问权限为privatestructpublic(因为struct要兼容C)

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

面试题

问题:C++中struct和class的区别是什么?

解答:C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是publicclass定义的类默认访问权限是private。注意:在继承和模板参数列表位置,structclass也有区别,后序给大家介绍。

封装

在这里插入图片描述

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

**封装本质上是一种管理,让用户更方便使用类。**比如:对于电脑这样一个复杂的设备,提供给用户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。

对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的,CPU内部是如何设计的等,用户只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可。

在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。

类的作用域

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

//learn.h文件
class Person
{
public:void shown();
public:char* _name;char* _sex;int _age;
};
//learn.c文件
void Person::shown()
{cout << _name << "-" << _sex << "-" << _age << endl;
}

这里需要指定shown()是属于Person这个类域

类的实例化

实例化:用类类型创建对象的过程叫做实例化

  1. 类是**对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没
    有分配实际的内存空间来存储它;**比如:入学时填写的学生信息表,表格就可以看成是一个
    类,来描述具体学生信息。类就像谜语一样,对谜底来进行描述,谜底就是谜语的一个实例。
    谜语:“年纪不大,胡子一把,主人来了,就喊妈妈” 谜底:山羊
  2. 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
class Person
{
public:void shown();
public:const char* _name;const char* _sex;int _age;
};void Person::shown()
{cout << _name << "-" << _sex << "-" << _age << "-" << endl;
}int main()
{Person p1;p1._name = "gwj";p1._sex = "男";p1._age = 20;p1.shown();return 0;
}

这里不能写成Person._name = "南桥"Person p1是用类实例化一个对象p1

类对象模型

计算类对象的大小

类对象中既有成员变量,又有成员函数,如何计算成员类对象大小?

先看下面代码:

// 类中既有成员变量,又有成员函数
class A1
{
public:void f1() {}
private:int _a;
};
// 类中仅有成员函数
class A2 {
public:void f2() {}
};
// 类中什么都没有---空类
class A3
{};int main()
{cout << "A1的大小" << sizeof(A1) << endl;cout << "A2的大小" << sizeof(A2) << endl;cout << "A3的大小" << sizeof(A3) << endl;return 0;
}

运行结果:
在这里插入图片描述

结论:一个类的大小,实际就是该类中”成员变量”之和,当然要注意内存对齐。注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。

结构体内存对齐:

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

关于结构体内存对齐,看参考小编文章:《C语言学习系列—>一篇带你了解结构体》

this指针

先定义一个类:Date

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(2022, 1, 11);d2.Init(2022, 1, 12);d1.Print();d2.Print();return 0;
}

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

C++中通过引入this指针解决该问题,即:**C++编译器给每个“非静态的成员函数“增加了一个隐藏
的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”
的操作,都是通过该指针去访问。**只不过所有的操作对用户是透明的,即用户不需要来传递,编
译器自动完成。

this指针特性

  1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。
  2. 只能在“成员函数”的内部使用
  3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
  4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递

在这里插入图片描述

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

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

相关文章

mysql-FIND_IN_SET查询优化

优化前 SELECTuser_id,user_name,real_name,PASSWORD,real_org_id,real_org_name,real_dept_id,real_dept_name, STATUS FROMsys_user WHEREis_del 0 AND find_in_set( lilong, login_user_account ) 优化后 SELECTuser_id,user_name,real_name,PASSWORD,real_org_id,real…

回归预测 | Matlab实现RIME-CNN-LSTM-Attention霜冰优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制)

回归预测 | Matlab实现RIME-CNN-LSTM-Attention霜冰优化卷积长短期记忆网络注意力多变量回归预测&#xff08;SE注意力机制&#xff09; 目录 回归预测 | Matlab实现RIME-CNN-LSTM-Attention霜冰优化卷积长短期记忆网络注意力多变量回归预测&#xff08;SE注意力机制&#xff0…

如何处理我们的文本数据成构建词表

我们拿到在拿到一堆语料数据&#xff0c;或者是在网络中爬取下来的文本数据如何处理成为模型能够训练的数据呢&#xff1f;这里有我们先经过停用词和按字分词的处理之后&#xff0c;得到的问答对文本数据&#xff0c;input_by_word.txt 和 target_by_word.txt 。其中&#xff0…

2024美赛预测算法 | 回归预测 | Matlab基于RIME-LSSVM霜冰算法优化最小二乘支持向量机的数据多输入单输出回归预测

2024美赛预测算法 | 回归预测 | Matlab基于RIME-LSSVM霜冰算法优化最小二乘支持向量机的数据多输入单输出回归预测 目录 2024美赛预测算法 | 回归预测 | Matlab基于RIME-LSSVM霜冰算法优化最小二乘支持向量机的数据多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效…

Docker进阶篇-Docker网络

一、描述 1、docker不启动&#xff0c;默认网络情况 查看网卡情况使用&#xff0c;ifconfig或者ip addr ens33&#xff1a;本机网卡 lo&#xff1a;本机回环网络网卡 virbr0:在CentoS 7的安装过程中如果有选择相关虚拟化的的服务安装系统后&#xff0c;启动网卡时会发现 …

Web实战丨基于Django的简单网页计数器

文章目录 写在前面Django简介主要程序运行结果系列文章写在后面 写在前面 本期内容 基于django的简单网页计数器 所需环境 pythonpycharm或vscodedjango 下载地址 https://download.csdn.net/download/m0_68111267/88795604 Django简介 Django 是一个用 Python 编写的高…

游戏找不到d3dcompiler_43.dll怎么办?多种5种解决方法分享

在运行游戏的过程中&#xff0c;系统遇到了一个关键性的问题&#xff0c;即无法成功找到名为“d3dcompiler_43.dll”的动态链接库文件。这一特定的dll文件对于游戏的正常启动和图形渲染至关重要&#xff0c;它的缺失可能会导致游戏无法运行或者画面无法正确显示。通常情况下&am…

day07-CSS高级

01-定位 作用&#xff1a;灵活的改变盒子在网页中的位置 实现&#xff1a; 1.定位模式&#xff1a;position 2.边偏移&#xff1a;设置盒子的位置 left right top bottom 相对定位 position: relative 特点&#xff1a; 不脱标&#xff0c;占用自己原来位置 显示模…

10秒搞定!隔壁奶奶都能搞定的幻兽帕鲁、雾锁王国开服指南

最近《幻兽帕鲁》和《雾锁王国》非常火热&#xff0c;玩过的小伙伴们都说非常上头&#xff01;有跟朋友对战需求的小伙伴们可以通过本文拥有一台高性价比的专用服务器&#xff0c;随时可以用来跟朋友一起玩游戏&#xff01; 敲重点&#xff01;&#xff01;&#xff01; 步骤…

2021-10-14 51蛋骗鸡1秒变动0-9按键控制并蜂鸣器响

缘由单片机程序设计与应用-Python-CSDN问答 #include "REG52.h" sbit K1 P3^0; sbit K2 P3^1; sbit K3 P3^2; sbit K4 P3^3; sbit bpP3^4; bit k1,wk0; unsigned char code SmZiFu[]{63,6,91,79,102,109,125,7,127,111,128,255,64};//0-9.消隐- unsigned char J…

【深度学习: 计算机视觉】如何改进计算机视觉数据集

【深度学习&#xff1a; 计算机视觉】如何改进计算机视觉数据集 训练模型并评估性能确定数据集需要改进的原因和位置收集或创建新的图像或视频数据重新训练机器学习模型并重新评估&#xff0c;直到达到所需的性能标准 机器学习算法需要大量数据集来训练、提高性能并生成组织所需…

基于SpringBoot+Vue的高校在线答疑管理系统

末尾获取源码作者介绍&#xff1a;大家好&#xff0c;我是墨韵&#xff0c;本人4年开发经验&#xff0c;专注定制项目开发 更多项目&#xff1a;CSDN主页YAML墨韵 学如逆水行舟&#xff0c;不进则退。学习如赶路&#xff0c;不能慢一步。 目录 一、项目简介 二、开发技术与环…

springwebflux高性能服务

场景&#xff1a; 分别使用springwebmvc 使用tomcat &#xff08;tomcat 9&#xff09;和springwebflux 做一个简单的接口 &#xff0c;该接口返回一个随机数 压测环境&#xff1a; 4C 8G ECS 使用tomcat 压测结果 Max 抖动的厉害 保持压测的参数不变 使用webflux 压测结果 …

Power Designer的使用 创建数据库表模型

几年前用过PowerDesigner&#xff0c;好几年没用&#xff0c;有点忘记了&#xff0c;在这里记个笔记&#xff0c;需要的时候翻一翻 PowerDesigner版本16.5 下面的例子是以MySQL数据库为准 生成C#实体类 一 安装 1.1 安装 不让放网盘链接&#xff0c;审核通不过。。。。 …

react 之 zustand

zustand可以说是redux的平替 官网地址&#xff1a;https://zustand-demo.pmnd.rs/ 1.安装 npm i zustand2.基础使用 // zustand import { create } from zustand// 1. 创建store // 语法容易出错 // 1. 函数参数必须返回一个对象 对象内部编写状态数据和方法 // 2. set是用来…

Maven高级知识——分模块开发、继承与聚合

目录 一、分模块设计与开发 1.1 不分模块的问题 1.2 分模块设计 二、 继承与聚合 2.1 继承 2.1.1 继承关系 2.1.2 版本锁定 2.1.2.1 场景 2.1.2.2 介绍 2.1.2.3 实现 2.1.2.4 属性配置 2.2 聚合 2.2.1 介绍 2.2.2 实现 2.3 继承与聚合对比 三、Maven打包方式&#xff08;jar、w…

应对手机数据丢失的5大安卓数据恢复软件

我们都去过那里。您的手机上的数据丢失了&#xff0c;现在无法恢复。这尤其令人恐惧&#xff0c;因为我们的手机上都有如此多的信息。从图片、应用程序、个人信息&#xff0c;甚至是来自可能已不复存在的亲人的短信和语音邮件。这种情况确实发生了&#xff0c;而且也不仅仅是An…

Leetcode—382. 链表随机节点【中等】(水塘抽样法)

2024每日刷题&#xff08;一零九&#xff09; Leetcode—382. 链表随机节点 算法思想 我们可以在初始化时&#xff0c;用一个数组记录链表中的所有元素&#xff0c;这样随机选择链表的一个节点&#xff0c;就变成在数组中随机选择一个元素 实现代码 /*** Definition for si…

STM32--USART串口(1)串口协议

一、通信接口 全双工&#xff1a;通信双方能够同时进行双向通信&#xff1b; 半双工&#xff1a;通信双方能够进行双向通信&#xff0c;但不能同时通信&#xff1b; 单工&#xff1a;只能从一个设备到另一个设备&#xff1b; 同步&#xff1a;接收方可以在时钟信号的指引下进…

线性代数:矩阵的秩

目录 一、矩阵的子式 二、矩阵的秩 三、重要性质定理推论 一、矩阵的子式 二、矩阵的秩 三、重要性质定理推论