C++的明星之我是类001

news2024/12/23 23:57:36

文章目录

    • 类定义格式
    • 访问限定符
    • 类域
  • 实例化
    • 实例化概念
    • 对象大小
  • this指针
  • 两道nt题目
    • 题目一
    • 题目二
  • C++和C语言实现stack对比


类定义格式

  • 新增一个关键字class,后加上类的名字,{}中为类的主体,类中的函数称为类的⽅法或者成员函数
  • 定义在类⾯的成员函数默认为inline

访问限定符

  • C++⼀种实现封装的⽅式,⽤类将对象的属性与⽅法结合在⼀块,让对象更加完善,通过访问权限选择性的将其接⼝提供给外部的⽤⼾使⽤
  • 有三种访问限定符,public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访问,protected和private是⼀样的,以后继承章节才能体现出他们的区别
  • 访问权限作⽤域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为⽌,如果后⾯没有访问限定符,作⽤域就到}即类结束
  • ⼀般成员变量都会被限制为private/protected,需要给别⼈使⽤的成员函数会放为public
    酱酱,到这里我们就可以看懂下面的代码啦
#include<iostream>
#include<assert.h>
using namespace std;
class Stack
{
public: // 共有就是说,客户可以使用咱们定义的方法
	void Init(int capacity = 4) 
	// 感觉类让函数的实现更加方便,这里不需要写函数的参数,因为就是通过这个类型的变量来调用的这个方法
	{
		_array = (int*)malloc(sizeof(int) * capacity);
		if (nullptr == _array)
		{
			perror("malloc申请空间失败");
			exit(1);
		}
		_capacity = capacity;
		_top = 0;
	}

	void Push(int x)
	{
		_array[_top++] = x;
	}

	int Top()
	{
		assert(_array);
		return _array[_top - 1];
	}

	void Destroy()
	{
		free(top > 0);
		_array = nullptr;
		_top = _capacity = 0;
	}

private: // 私有,就是说客户不能使用不能改变的东西
	//成员变量
	int* _array;
	size_t _capacity;
	size_t _top;
};

int main()
{
	Stack st; // 类名就是对象(变量)类型
	st.Init(); // 和结构体一样,通过.操作符来访问类里的元素,这里就是类里的方法
	st.Push(1);
	st.Push(2);
	cout << st.Top() << endl;
	st.Destroy();
}

以上就是类的一个基本用法
C++中struct也可以定义类,C++兼容C中struct的⽤法,同时struct升级成了类,明显的变化是struct中可以定义函数,⼀般情况下我们还是推荐⽤class定义类

struct Person
{
public:
	void Init(const char* name, int age, int tel)
	{
		strcpy(_name, name);
		_age = age;
		_tel = tel;
	}

	void Print()
	{
		cout << "姓名:" << _name << endl;
		cout << "年龄:" << _age << endl;
		cout << "电话:" << _tel << endl;
	}

private:
	char _name[10];
	int _age;
	int _tel;
};

int main()
{
	Person p;
	p.Init("zhangsan", 18, 13409873);
	p.Print();
}

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

类域

  • 类定义了⼀个新的作⽤域,类的所有成员都在类的作⽤域中,在类体外定义成员时(声明和定义分离),需要使⽤::作⽤域操作符指明成员属于哪个类域

实例化

实例化概念

  • ⽤类类型在物理内存中创建对象的过程,称为类实例化出对象
  • 类是对象进⾏⼀种抽象描述,是⼀个模型⼀样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,⽤类实例化出对象时,才会分配空间
    我们看下面代码
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()
{
	//Data::_year = 1; //err 这里的对象是类的一部分
	Date d1; // 类实例化出对象
	Date d2;
	d1.Init(2024, 3, 31);
	d1.Print();
	d2.Init(2024, 7, 5);
	d2.Print();
	return 0;
}

对象大小

首先我们思考的问题就是,在计算类的大小的是时候,要不要加上函数地址。结论是不需要加,只需要考虑内存对齐的问题,为什么呢?
我们想,如果两个对象都调用类里的同一个成员函数,这两个成员函数的地址是一样的,我们没有必要创建一个变量,就申请一片空间来存放函数的地址,这样会造成冗余,我们只用把这些方法都放在一个公共的地方,使用的时候直接用就行
而成员变量不一样,每一个对象的成员变量都不相同,所以每一个对象都只用为成员变量开辟空间
下面我们复习一下对齐规则

  • 第⼀个成员在与结构体偏移量为0的地址处
  • 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处
  • 注意:对⻬数=编译器默认的⼀个对⻬数与该成员⼤⼩的较⼩值
  • VS中默认的对⻬数为8
  • 结构体总⼤⼩为:最⼤对⻬数(所有变量类型最⼤者与默认对⻬参数取最⼩)的整数倍
    为啥要内存对齐
    答:为了提高访问效率
    看下面的实例
    在这里插入图片描述
    假设变量在内存中存储不对齐,也就是图中下面的存储方式,我们想要访问_i,就需要访问两次,因为计算机读取数据时是在一个整数倍读取的,比方说三十二位机器,一次就是读取四个字节的数据,且只能在4的整数倍位置读取数据,那么按照图中下面的存储方式,就要访问两次,而按照内存对齐的方式存储,只需要访问一次就可以读取到_i
    我们再看一个实例

class A
{
public:
	void print()
	{

	}

private:
	char _ch;
	int _i;
};

class B
{
	void print()
	{

	}
};

class C
{};

int main()
{
	cout << sizeof(A) << endl; // 8
	cout << sizeof(B) << endl; // 1
	cout << sizeof(C) << endl; // 1 
	return 0;
}

对于没有成员变量的类,默认开一个字节的空间,起占位作用,不存储有效数据,表示对象存在

this指针

  • 我们再返回去看一下Data类,现在就有一个疑问了,d1调⽤Init和Print函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?那么这⾥就要看到C++给了⼀个隐含的this指针解决这⾥的问题
  • 编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this指针。⽐如Date类的Init的真实原型为,void Init(Date* const this, int year, int month, int day)
    所以调用的时候实际上是这样
d1.Iint(&d1, 2024,3, 31);

只不过指针是被省略掉的,所以实参的取地址也省略

  • 类的成员函数中访问成员变量,本质都是通过this指针访问的,如Init函数中给_year赋值,this->_year = year;
  • C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显⽰使⽤this指针
class Date
{
public:          //不可以显示的加
	// void Init(Date* const this, int year, int month, int day)
	void Init(int year, int month, int day)
	{
		// 编译报错:error C2106 : “ = ” :左操作数必须为左值
		// this = nullptr;
		// this->_year = year;
		_year = year;
		this->_month = month;
		this->_day = day;
	}
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
		cout << this->_year << "/" << this->_month << "/" << this->_day << endl;//两种都可以
	}
private:
	// 这⾥只是声明,没有开空间
	int _year;
	int _month;
	int _day;
};
int main()
{
	// Date类实例化出对象d1和d2
	Date d1;
	Date d2;
	// d1.Init(&d1, 2024, 3, 31);
	d1.Init(2024, 3, 31);
	d1.Print();
	d2.Init(2024, 7, 5);
	d2.Print();
	return 0;
}

一个小问题:this指针存在于内存的哪个区域呢?
答案是存在于栈区,因为this是一个隐含的形参,形参就是函数的参数,函数参数存在于栈区

两道nt题目

题目一

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

A:编译报错 B:运行崩溃 C:正常运行
这个题答案选C
解析:A选项编译报错,说明是语法错误,首先排除,p虽然是一个空指针,且调用了函数Print,但是成员函数的地址没有存在于*p中,并且Print方法没有访问成员变量,所以不存在解引用,所以正常运行

题目二

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

结果是运行崩溃
解析:cout << this->_a << endl相当于这样出现了解引用,所以程序崩溃

C++和C语言实现stack对比

C版

#define  _CRT_SECURE_NO_WARNINGS 1
#include"stack_c.h"

void STInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

void STDestroy(ST* ps)
{
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}

void STPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->capacity == ps->top)
	{
		//扩容
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->a, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
	ps->a[ps->top] = x;
	ps->top++;
}

bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	ps->top--;
}

STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	return ps->a[ps->top - 1];
}

int main()
{
	ST st;
	STInit(&st);
	STPush(&st, 1);
	STPush(&st, 2);
	STPush(&st, 3);
	STPush(&st, 4);
	STPush(&st, 5);
	while (!STEmpty(&st))
	{
		printf("%d\n", STTop(&st));
		STPop(&st);
	}
	STDestroy(&st);
	return 0;
}

C++版

#define  _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<assert.h>
using namespace std;

typedef int Datatype;
class stack
{
public:
	void Init(int n = 4)
	{
		_a = (Datatype*)malloc(sizeof(Datatype) * n);
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(1);
		}
		_capacity = 4;
		_top = 0;
	}

	void Push(int x)
	{
		if (_capacity == _top)
		{
			int newcapacity = _capacity * 2;
			Datatype* tmp = (Datatype*)realloc(_a, newcapacity *sizeof(Datatype));
			if (tmp == NULL)
			{
				perror("realloc fail");
				return;
			}
			_a = tmp;
			_capacity = newcapacity;
		}
		
		_a[_top++] = x;
	}
	void Pop()
	{
		assert(_top > 0);
		--_top;
	}
	bool Empty()
	{
		return _top == 0;
	}
	int Top()
	{
		assert(_top > 0);
		return _a[_top - 1];
	}
	void Destroy()
	{
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	Datatype* _a;
	int _capacity;
	int _top;
};

int main()
{
	stack s;
	s.Init();
	s.Push(1);
	s.Push(2);
	s.Push(3);
	s.Push(4);
	while (!s.Empty())
	{
		printf("%d\n", s.Top());
		s.Pop();
	}
	s.Destroy();
	return 0;
}

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

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

相关文章

OccLLaMA:首个结合3D占用预测、语言、行为构建的生成式世界模型

导读&#xff1a; OccLLaMA是首个结合3D占用预测作为视觉表征的生成式世界模型。大量实验表明&#xff0c;OccLLaMA在多个任务上实现了不错的性能&#xff0c;包括4D占用预测、运动规划和视觉问答&#xff0c;展示了其作为自动驾驶基础模型的潜力。©️【深蓝AI】编译 1. 研…

如何在谷歌浏览器上玩大型多人在线游戏

在如今的数字时代&#xff0c;谷歌浏览器已经成为了许多人上网冲浪的首选工具。除了浏览网页、观看视频之外&#xff0c;你还可以在谷歌浏览器上畅玩各种大型多人在线游戏。本文将为你详细介绍如何在谷歌浏览器上玩大型多人在线游戏的步骤。 &#xff08;本文由https://chrome…

【Java代码审计】敏感信息泄露篇

【Java代码审计】敏感信息泄露篇 1.敏感信息泄露概述2.TurboMail 5.2.0 敏感信息泄露3.开发组件敏感信息泄露1.敏感信息泄露概述 敏感信息是业务系统中对保密性要求较高的数据,通常包括系统敏感信息以及应用敏感信息 系统敏感信息指的是业务系统本身的基础环境信息,例如系统…

望繁信科技CTO李进峰受邀在上海外国语大学开展流程挖掘专题讲座

2023年&#xff0c;望繁信科技联合创始人兼CTO李进峰博士受邀在上海外国语大学国际工商管理学院&#xff08;以下简称“上外管院”&#xff09;开展专题讲座&#xff0c;畅谈流程挖掘的发展及对企业数字化转型的价值。演讲吸引了上外教授和来自各行各业的领军企业学员百余人。 …

句子成分——每日一...

一、 "Who made you read so many books and realize that there is a bigger world beyond Shuangshui Village..." If you have been working from sunrise to sunset in this world since childhood, you will have the same ideal as many villagers: after a …

嵌入式硬件工程师与嵌入式软件工程师的区别(详细版)

嵌入式硬件工程师与嵌入式软件工程师的区别&#xff08;详细版&#xff09; 这里写目录标题 嵌入式硬件工程师与嵌入式软件工程师的区别&#xff08;详细版&#xff09;什么是嵌入式硬件工程师&#xff1f;什么是嵌入式软件工程师&#xff1f;嵌入式硬件工程师与嵌入式软件工程…

关于vue2+uniapp+uview+vuex 私募基金项目小程序总结

1.关于权限不同tabbar处理 uniapp 实现不同用户展示不同的tabbar(底部导航栏)_uniapp tabbar-CSDN博客 但是里面还有两个问题 一个是role应该被本地存储并且初始化 第二个问题是假设我有3个角色 每个角色每个tabbar不一样的&#xff0c;点击tabbar时候会导致错乱 第三个问题…

webpack使用

一、简介 概述 本次使用webpack4进行构建打包 二、webpack 安装webpack、webpack-cli npm install webpack4.2.0 webpack-cli4.2.0 -D 三、loader 加载器概述 raw-loader&#xff1a;加载文件原始内容&#xff08;utf-8&#xff09; file-loader&#xff1a;把文件输出…

【深度学习】(4)--卷积神经网络

文章目录 卷积神经网络一、画面不变性二、图像识别三、卷积网络结构1. 原理2. 卷积层3. 池化层4. 全连接层 四、感受野 总结 卷积神经网络 卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;简称CNN&#xff09;是一种深度学习模型&#xff0c;特别适用于处理…

探索 Snowflake 与 Databend 的云原生数仓技术与应用实践 | Data Infra NO.21 回顾

上周六&#xff0c;第二十一期「Data Infra 研究社」在线上与大家相见。活动邀请到了西门子数据分析师陈砚林与 Databend 联合创始人王吟&#xff0c;为我们带来了一场关于 Snowflake 和 Databend 的技术探索。Snowflake&#xff0c;这个市值曾超过 700 亿美元的云原生数据仓库…

20240926 关于Goland处理wsl-GOROOT原理猜测

GOROOT的原理 go sdk与java jdk类似&#xff0c;是go的编译工具链的集合。 在windows上&#xff0c;我们通过在系统环境变量中添加GOROOT并设置为go sdk地址&#xff0c;使得命令行可以访问到go sdk并执行go test、build等命令&#xff0c;这样设置的变量是全局生效的&#x…

zico2打靶记录

一、环境搭建 下载地址&#xff1a;https://download.vulnhub.com/zico/zico2.ova 直接双击下载的.ova文件即可在VMware中打开 设置好保存路径后在虚拟机的设置中删除仅主机这个网卡 然后启动靶机 二、信息收集 扫描靶机ip arp-scan -l 扫描一下开放的端口 nmap -p- -sV…

C++面向对象基础

目录 一.函数 1.内联函数 2.函数重载 3.哑元函数 二.类和对象 2.1 类的定义 2.2 创建对象 三. 封装&#xff08;重点&#xff09; 四. 构造函数 constructor&#xff08;重点&#xff09; 4.1 基础使用 4.2 构造初始化列表 4.3 构造函数的调用方式&#xff08;掌握…

如何守护变美神器安全?红外热像仪:放开那根美发棒让我来!

随着智能家电市场的迅速发展&#xff0c;制造商们越来越关注生产过程中效率和质量的提升。如何守护变美神器安全&#xff1f;红外热像仪&#xff1a;放开那根卷发棒让我来&#xff01; 美发棒生产遇到什么困境&#xff1f; 美发棒生产过程中会出现设备加热不均情况&#xff0c…

【pytorch】pytorch入门4:神经网络的卷积层

文章目录 前言一、定义概念 缩写二、性质三、代码总结参考文献 前言 使用 B站小土堆课程的笔记 一、定义概念 缩写 卷积层是神经网络中用于突出特征来进行分类任务的层。 二、性质 卷积核例子&#xff1a;vgg16 model 三、代码 添加库 python代码块import os import …

无线领夹麦克风哪个牌子好,2024年新款领夹麦克风推荐

在短视频和直播风靡的当下&#xff0c;音频质量成为了衡量内容品质的重要标尺。市面上琳琅满目的无线领夹麦克风产品&#xff0c;却让许多创作者陷入了选择困难中&#xff0c;高昂的价格、复杂的操作、以及参差不齐的音质表现&#xff0c;让不少人在追求专业音频的道路上交了“…

Excel中用位置筛选解法

有 2022 年 1 月的日销售额统计表如下所示&#xff1a; 筛选出偶数日的销售额&#xff1a; spl("E(?1).select(#%20)",A1:B32)#表示当前行号 免费课程、软件免费下载

智慧公厕:引领公共卫生新潮流@卓振思众

随着科技的不断进步&#xff0c;智慧公厕应运而生&#xff0c;为人们带来了全新的如厕体验。作为智慧公厕厂家&#xff0c;我们致力于打造更加舒适、便捷、环保的公共厕所。智慧公厕究竟有哪些神奇之处呢&#xff1f;让我们一起来揭开它的神秘面纱。【卓振思众】 一、环境监测&…

基于SpringBoot + Vue的轿车数字化管理系统

文章目录 前言一、详细操作演示视频二、具体实现截图三、技术栈1.前端-Vue.js2.后端-SpringBoot3.数据库-MySQL4.系统架构-B/S 四、系统测试1.系统测试概述2.系统功能测试3.系统测试结论 五、项目代码参考六、数据库代码参考七、项目论文示例结语 前言 &#x1f49b;博主介绍&a…

餐厅包厢预订小程序

餐厅包间预订小程序的功能可以包括以下几个方面&#xff1a; 用户注册与登录&#xff1a; 用户可以通过手机号、微信等方式注册和登录。 包间展示&#xff1a; 提供各类包间的详细信息&#xff0c;包括图片、容纳人数、设施、装修风格等。 实时预订&#xff1a; 用户可以选择日…