【C++】---类和对象(上)入门

一、类的定义

1.那么众所周知,C语言是面向过程的,关注的是过程,分析出求解的步骤,通过函数的调用来逐步解决问题
2.而C++是基于面向对象的,关注的是对象将一件事情拆分成不同的对象,靠对象之间交互完成!

class classname
{
	// 类体:由 成员变量 和 成员函数 组成

};// 一定要注意后面的分号

3.class是定义类的关键字classname是类的名字{}中的为类的主体,注意:类结束时后面的分号不能省略
4.类中的内容:称为类的成员:类中的变量称为成员变量或者类的属性。类中的函数称为成员函数或者类的方法。

二、类的访问限定符和封装

1.类的访问限定符

对象的属性(变量)和方法(函数)结合在一起,让对象更加完善
通过访问权限选择性的将类的接口提供给外部用户进行访问使用
C++的访问限定符分为以下几种:

  1. public:被public修饰的成员在类外可以直接被访问
  2. protected和private:被protected和private所修饰的成员在类外不能被直接访问!(此处protected和private是类似的)
  3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
  4. 如果后面没有访问限定符,作用域就到 } 即类结束。
  5. class的默认访问权限为privatestruct为的默认访问权限public(因为struct要兼容C)
    注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别
    问题:C++中struct和class的区别是什么?
    解答:C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来
    定义类
    。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类
    默认访问权限是private
    。注意:在继承和模板参数列表位置,struct和class也有区别,后序给大
    家介绍。

2.类的封装

面向对象的三大特性:封装、继承、多态
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来
和对象进行交互。

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

三、类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用 :: 作用域解析符指明成员属于哪个类域。整个域是一个整体,成员变量无论在成员函数上面或者下面都可以进行访问。

#include<stdlib.h>
#include<iostream>
using namespace std;
typedef int STDataType;
 
class Stack
{
public:
	//初始化
	void StackInit(int initSize);
	
public:
	STDataType* a;
	int size;
	int capacity;
 
};
 
//指明成员属于Stack类
void Stack::StackInit(int initSize = 4)
{
		a = (STDataType*)malloc(sizeof(STDataType) * 4);
		size = 0;
		capacity = initSize;
}

四、类的实例化

1.什么是类的实例化

什么是类的实例化?
用 类 创建 对象 的过程!

2.为什么要对类进行实例化?

1.类是对 对象描述的一个东西一个模板,就是一个空壳。这里面只限定了类有哪些成员,定义出了一个类,但是并没有分配实际的空间来储存它。
(就比如说:入学时填的学生信息表,那个学生信息表的表格就是一个类,它就相当于一个空壳
2.一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量

3.具体理解实例化

在这里插入图片描述
在这里插入图片描述
实例:

#include <stdlib.h>
#include<iostream>
using namespace std;
 
typedef int STDataType;
 
struct Stack
{
	//初始化
	void StackInit(int initSize = 4)
	{
		a = (STDataType*)malloc(sizeof(STDataType) * 4);
		size = 0;
		capacity = initSize;
	}
 
	STDataType* a;
	int size;
	int capacity;
 
};
 
int main()
{
	
	Stack st; //实例化对象
 
    return 0;
}

4.对定义的深刻理解

注意:对变量定义成功的标志:该变量在内存中开了空间


class Date
{
//private:
public:
	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;
	}

};

int main()
{
	//Date D1;//此处对类进行了定义!
	D1._year;//为啥不能访问?因为:_year没有定义

	return 0;
}

五、类对象模型

1.如何计算类的大小

1.遵循内存对齐原则
我们直接通过上实例代码进行理解:

//既有 成员函数 又有 成员变量
class A1
{
public:
	void f1(){}

private:
	int _a;
};
//只有 成员函数
class A2
{
public:
	void f2(){}
};
//空类
class A3
{

};
int main()
{


	cout << sizeof(A1) << endl;
	cout << sizeof(A2) << endl;
	cout << sizeof(A3) << endl;

	return 0;
}

在这里插入图片描述
C++规定:没有成员变量的类对象,它的大小为1字节,占位标识类存在过
结论:一个类的大小,实际就是该类中”成员变量”之和,当然要注意内存对齐
注意:空类的大小,空类比较特殊,编译器给了空类1个字节来唯一标识这个类的对象。

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

2.类的对象储存方式

假如对象中包含类的各个成员,既包含成员变量,又包含成员函数,由于每个对象中成员变量是不同的,但调用的是同一份成员函数,如果按照此种方式存储,当一个类创建多个对象时,每个对象中都会保存一份成员函数代码,相同代码保存多次,会浪费空间。
在这里插入图片描述

因此C++采用类对象中只存储成员变量成员函数存放在公共代码段中的方式来存储类的对象。
在这里插入图片描述

//既有 成员函数 又有 成员变量
class A1
{
public:
	void f1(){}

private:
	int _a;
};
//只有 成员函数
class A2
{
public:
	void f2(){}
};
//空类
class A3
{

};
int main()
{
	A1 a1;
	A2 a2;
	A3 a3;
	cout << sizeof(A1) << endl;
	cout << sizeof(A2) << endl;
	cout << sizeof(A3) << endl;

	cout << &a1 << endl;
	cout << &a2 << endl;
	cout << &a3 << endl;

	return 0;
}

在这里插入图片描述
尽管对象a2的类中没有成员变量仅有成员函数,对象a3的类中既没有成员变量也没有成员函数,但是它们的地址不同,表明对象a2和对象a3存在过。

六、this指针

1.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++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成

2.this指针的特性

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

(1)例如:如果定义两个对象,d1和d2如何访问自己的年月日呢?两个对象调用的是同一份成员函数,如何做到各自初始化各自的?

#include <iostream>
using namespace std;

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

int main()
{
	Date d1;
	Date d2;
	d1.Init(2024, 2, 15);
	d2.Init(2024, 2, 16);

	d1.Print();
	d2.Print();
	return 0;
}

在这里插入图片描述

因为编译器做了处理,Init函数的入参不是3个参数,实际上是4个参数,编译器会增加一个隐含的参数:this指针,编译器会把对象的地址传给this

int main()
{
	Date d1;
	d1.Init(2024, 2, 15);//实际为d1.Init(&d1,2024,2,15)
 
	Date d2;
	d2.Init(2024, 2, 16);//实际为d2.Init(&d2,2024,2,16)
 
    return 0;
}

编译器增加的隐含的this指针参数,即void Init(Date* this, int year, int month, int day),作为形参,this指针存在于栈中。

3.两个例题充分理解

1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
比特就业课
8.3. C语言和C++实现Stack的对比
1. C语言实现
public:
 void Print()
 {
 cout << "Print()" << endl;
 }
private:
 int _a;
};
int main()
{
 A* p = nullptr;
 p->Print();
 return 0;
}

这里变量p是一个类的指针,把它置为nullptr,然后把它当做指针,赋给this指针,在语法上并没有错误所以不会编译出错,然后访问函数Print,但是访问的时候,他并没有对this指针所指向的内容进行解引用(访问)
所以:选C

2.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{ 
public:
    void PrintA() 
   {
        cout<<_a<<endl;
   }
private:
 int _a;
};
int main()
{
    A* p = nullptr;
    p->PrintA();
    return 0;
}

这里调用了函数,打印a,就着nullptr作为形参传递给this指针,进行解引用,就会运行崩溃!!!

好了,今天的分享就到这里了
如果对你有帮助,记得点赞👍+关注哦!
我的主页还有其他文章,欢迎学习指点。关注我,让我们一起学习,一起成长吧!
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

消息队列RabbitMQ-使用过程中面临的问题与解决思路

消息队列在使用过程中会出现很多问题 首先就是消息的可靠性&#xff0c;也就是消息从发送到消费者接收&#xff0c;消息在这中间过程中可能会丢失 生产者到交换机的过程、交换机到队列的过程、消息队列中、消费者接收消息的过程中&#xff0c;这些过程中消息都可能会丢失。 …

【数据结构】LRU Cache

文章目录 LRUCache LRUCache 1. LRUCache是一种缓存的替换技术&#xff0c;在CPU和main memory之间根据计算机的局部性原理&#xff0c;往往会采用SRAM技术来构建CPU和主存之间的高速缓存&#xff0c;DRAM(dynamic random access memory)用于构建主存&#xff0c;LRUCache这种…

【正点原子STM32】TIMER 定时器(软件定时原理、定时器定时原理、分类和特性、基本定时器(影子寄存器和U事件和UI中断))

一、定时器概述 1.1、软件定时原理1.2、定时器定时原理1.3、STM32定时器分类1.4、STM32定时器特性表1.5、STM32基本、通用、高级定时器的功能整体区别 二、基本定时器 2.1、基本定时器简介2.2、基本定时器框图2.3、定时器计数模式及溢出条件2.4、定时器中断实验相关寄存器2.…

【数据结构】二叉树的三种遍历

目录 一、数据结构 二、二叉树 三、如何遍历二叉树 一、数据结构 数据结构是计算机科学中用于组织和存储数据的方式。它定义了数据元素之间的关系以及对数据元素的操作。常见的数据结构包括数组、链表、栈、队列、树、图等。 数组是一种线性数据结构&#xff0c;它使用连续…

[Vue warn]: Duplicate keys detected: ‘1‘. This may cause an update error.

[Vue warn]: Duplicate keys detected: ‘1‘. This may cause an update error.——> Vue报错&#xff0c;key关键字不唯一&#xff1a; 解决办法&#xff1a;修改一下重复的id值&#xff01;&#xff01;&#xff01;

C#系列-使用 Minio 做图片服务器实现图片上传 和下载(13)

1、Minio 服务器下载和安装 要在本地安装和运行 MinIO 服务器&#xff0c;你可以按照以下 步骤进行操作&#xff1a; 1. 访问 MinIO 的官方网站&#xff1a;https://min.io/&#xff0c;然后 点击页面上的”Download”按钮。 2. 在下载页面上&#xff0c;选择适合你操作系统的 …

(16)Hive——企业调优经验

前言 本篇文章主要整理hive-3.1.2版本的企业调优经验&#xff0c;有误请指出~ 一、性能评估和优化 1.1 Explain查询计划 使用explain命令可以分析查询计划&#xff0c;查看计划中的资源消耗情况&#xff0c;定位潜在的性能问题&#xff0c;并进行相应的优化。 explain执行计划…

[C#] 如何调用Python脚本程序

为什么需要C#调用python&#xff1f; 有以下几个原因需要C#调用Python&#xff1a; Python拥有丰富的生态系统&#xff1a;Python有很多强大的第三方库和工具&#xff0c;可以用于数据科学、机器学习、自然语言处理等领域。通过C#调用Python&#xff0c;可以利用Python的生态系…

HiveSQL——统计当前时间段的有客人在住的房间数量

注&#xff1a;参考文章&#xff1a; HiveSQL一天一个小技巧&#xff1a;如何统计当前时间点状态情况【辅助变量累计变换思路】_sql查询统计某状态出现的次数及累计时间-CSDN博客文章浏览阅读2k次&#xff0c;点赞6次&#xff0c;收藏8次。本文总结了一种当前时间点状态统计的…

【JAVA-Day86】守护线程

守护线程 守护线程摘要引言1. 了解守护线程&#xff1a;它是什么&#xff1f;&#x1f47b;特点和用途示例代码 2. 为何我们需要守护线程&#xff1f;&#x1f47b;辅助性任务处理不阻止程序的正常运行重要的清理工作示例代码&#x1f4da; 3. 如何创建和管理守护线程&#xff…

QT 工具栏 状态栏 停靠部件 核心部件

添加/删除工具栏 删除工具栏方法和删除菜单栏方法一样&#xff0c;不过工具栏可以有多个&#xff0c;所以每次右键MainWindow对象&#xff0c;都可以看到添加工具栏的选项。 工具栏添加动作 新添加的QAction对象会在动作编辑器里找到&#xff08;Action Editor&#xff09;&a…

Java毕业设计-基于springboot的学院物资管理系统-第73期

获取源码资料&#xff0c;请移步从戎源码网&#xff1a;从戎源码网_专业的计算机毕业设计网站 项目介绍 基于springboot的学院物资管理系统&#xff1a;前端thymeleaf、jquery、layui&#xff0c;后端 maven、springmvc、spring、mybatis&#xff0c;有配套报告文档&#xff…

微信小程序的疑惑总结

未解决&#xff1a; 1.storebindings 这里的storebindings是什么 2.空行怎么写&#xff1f; 我用这个<text>\n</text>写&#xff0c;在模拟器上好使&#xff0c;在真机上显示\n 解决方法&#xff1a;在组件里写class类名&#xff0c;wxss里面改高度 已解决&am…

LD-802D-X6

LD-802D-X6足浴按摩器&#xff0c;买个给老人家&#xff0c;解决泡脚越泡越冷&#xff0c;调节温度和定式问题&#xff0c; 按摩功能老人体验说太痒&#xff0c;转太快了&#xff0c;哈哈 下面是安装步骤使用说明 其实这包零件就是安装底部4个轮子&#xff0c;4个轮子的中间滚…

【分享】图解ADS+JLINK调试ARM

文章是对LPC2148而写的&#xff0c;但是对三星的44B0芯片同样适用&#xff0c;只需要在选择时将相应的CPU选择的S3C44B0就可以了。 JLINK在ADS下调试心得 前两天一个客户用jlink在ADS下调试LPC2148总报错&#xff0c;这个错误我之前在调试LPC2200的时候也碰到过&#xff0c;后…

Nuxt3+Vue3(Composition API)+TS+Vite+Ant Design Vue 搭建

最近官网搭建选择了nuxtjs&#xff0c;由于框架更新了&#xff0c;其中语法也有很多变化&#xff0c;中间遇到了一些问题点做下总结。 nuxt3官方文档地址&#xff1a;https://nuxt.com/docs/getting-started/installation 安装 在安装Nuxt3之前&#xff0c;你需要保证你的nod…

【AIGC】Stable Diffusion的常见错误

Stable Diffusion 在使用过程中可能会遇到各种各样的错误。以下是一些常见的错误以及可能的解决方案&#xff1a; 模型加载错误&#xff1a;可能出现模型文件损坏或缺失的情况。解决方案包括重新下载模型文件&#xff0c;确保文件完整并放置在正确的位置。 依赖项错误&#x…

【C深度解剖】前置++与后置++

简介&#xff1a;本系列博客为C深度解剖系列内容&#xff0c;以某个点为中心进行相关详细拓展 适宜人群&#xff1a;已大体了解C语法同学 作者留言&#xff1a;本博客相关内容如需转载请注明出处&#xff0c;本人学疏才浅&#xff0c;难免存在些许错误&#xff0c;望留言指正 作…

飞天使-k8s知识点17-kubernetes实操2-pod探针的使用

文章目录 探针的使用容器探针启动实验1-启动探针的使用-startupprobeLiveness Probes 和 Readiness Probes演示若存在started.html 则进行 探针的使用 kubectl edit deploy -n kube-system corednslivenessprobe 的使用 livenessProbe:failureThreshold: 5httpGet:path: /heal…

ubuntu22.04@laptop OpenCV Get Started: 009_image_thresholding

ubuntu22.04laptop OpenCV Get Started: 009_image_thresholding 1. 源由2. image_thresholding应用Demo2.1 C应用Demo2.2 Python应用Demo 3. 重点分析3.1 Binary Thresholding ( THRESH_BINARY )3.2 Inverse-Binary Thresholding ( THRESH_BINARY_INV )3.3 Truncate Threshold…