C++-类与对象基础

news2025/1/23 10:45:09

一,类的定义

1.1类定义格式

class为定义类的关键字,Stack为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为mian类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。比如我们下面的一个简单的栈结构例子(不完整,作为引子使用):

using namespace std;

class Stack
{
public:
	void Init(int n = 4)
	{
		int* tmp = (int*)malloc(sizeof(int) * n);
		if (tmp == nullptr)
		{
			perror("realloc fail!");
			exit(EXIT_FAILURE);
		}
		_arr = tmp;
		top = 0;
		capacity = n;
	}
	void Destory()
	{
		free(_arr);
		_arr = nullptr;
		top = capacity = 0;
	}
private:
	int* _arr;
	int top;
	int capacity;
};

int main()
{
	Stack d1;
	d1.Destory();
	return 0;
}

我们可以看到,类的使用方法与我们C中所学习的结构体非常类似,且class定义的类名可以直接代表类型,不需要我们再去使用typedef,而我们的C++中strcut也升级为了类,在struct中可以定义函数,但我们一般还是在C++中使用class定义类。

除此之外,我们的类的成员函数前都默认加有我们的inline:

void Init(int n = 4)//inline void Init(int n = 4)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == nullptr)
	{
		perror("realloc fail!");
		exit(EXIT_FAILURE);
	}
	_arr = tmp;
	top = 0;
	capacity = n;
}

1.2访问限定符

我们注意到,在上面的栈代码中有public与private,这就是我们的类的访问限定符,我们的类访问限定符一共有三种:

1.public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访问,protected和private是⼀样的,以后介绍到继承部分时才能体现出他们的区别。

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

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

4.⼀般成员变量都会被限制为private/protected,需要给别⼈使用的成员函数会放为public。

1.3类域 

这部分其实与我们的namespace有些许类似,类域影响的是编译的查找规则,就比如说我们要直接使用上面代码中的Init函数,如果不指定类域Stack,那么编译器就把Init当成全局函数,那么编译时,找不到arr等成员的声明/定义在哪里,就会报错。指定类域Stack,就是知道Init是成员函数,当前域找不到的arr等成员,就会到类域中去查找。

class Stack
{
public:
	void Init(int n = 4)
	{
		int* tmp = (int*)malloc(sizeof(int) * n);
		if (tmp == nullptr)
		{
			perror("realloc fail!");
			exit(EXIT_FAILURE);
		}
		_arr = tmp;
		top = 0;
		capacity = n;
	}
private:
	int* _arr;
	int top;
	int capacity;
};

int main()
{
    Stack::Init();//正确调用方法
    Init();//编译器找不到Init函数
	return 0;
}

二,实例化

 2.1实例化的概念

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

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

3.⼀个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量。所以简单来说,我们的类就像盖房子的图纸一样,对着图纸建造出我们的房子就是我们的实例化。

2.2对象大小

我们在上面说过,类的定义中是有函数的,成员变量的大小我们在C语言中就已经详细了解过了,不多赘述。我们来看类的成员函数,假如我们的成员函数也是占有空间的,那我们去定义100个类,是不是就要去至少实例化100个成员函数,但我们知道,在实际使用的时候,拿我们上面的Stack来举例:

class Stack
{
public:
	void Init(int n = 4)
	{
		int* tmp = (int*)malloc(sizeof(int) * n);
		if (tmp == nullptr)
		{
			perror("realloc fail!");
			exit(EXIT_FAILURE);
		}
		_arr = tmp;
		top = 0;
		capacity = n;
	}
	void Destory()
	{
		free(_arr);
		_arr = nullptr;
		top = capacity = 0;
	}
private:
	int* _arr;
	int top;
	int capacity;
};

int main()
{
	Stack d1;
    Stack d2;
	d1.Destory();
    d2.Destory();
	return 0;
}

可以看到,两个相同的类用的是同一个函数,这样不就造成了不必要的实例化了。其实,函数被编译后是⼀段指令,对象中没办法存储,这些指令存储在⼀个单独的区域(代码段),那么对象中非要存储的话,只能是成员函数的指针。同时函数指针是不需要存储的,函数指针是⼀个地址,调用函数被编译成汇编指令[call 地址], 其实编译器在编译链接时,就要找到函数的地址,不是在运行时找,只有动态多态是在运行时找,就需要存储函数地址,这个我们以后的文章会介绍。

 接下来我们来看几个例子:

class A
{
	public :
	void Print()
	{
		cout << _ch << endl;
	}
private:
	char _ch;
	int _i;
};
class B
{
	public :
	void Print()
	{
		//...
	}
};
class C
{};

对于A,我们可以轻松的算出其大小为8byte,但是C和B呢。猛一看,我们上面不是说过,只有实例化的对象才会分配空间,所以按照常理来说B和C均为0,但是实际上为1,为什么?

B b1;
C c1;

如果为0,那我们上面定义的两个b1和c1所分配的空间就是0,如果⼀个字节都不给,怎么表示对象存在过呢,所以这里给1字节,纯粹是为了占位标识对象存在。

三,this指针

当我们定义了两个Stack对象时,编译器是如何区分d1与d2呢。事实上,编译器会在编译的时候自动在后面补上一个this指针:
 

d1.Init(&d1);
d2.Init(&d2);

void Init(int n = 4)//实际调用后void Init(Stack const* this,int n = 4)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == nullptr)
	{
		perror("realloc fail!");
		exit(EXIT_FAILURE);
	}
	_arr = tmp;
	top = 0;
	capacity = n;
}

所以类的成员函数中访问成员变量,本质都是通过this指针访问的。除此之外,C++规定不能在实参和形参的位置显示的写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针。

下面让我们来看两个经典案例:

乍一看两个都对空指针进行了解引用,二者均会产生运行崩溃(切记编译错误为语法上的错误),但实际上只有第二种情况会报错。我们上面也说过,成员函数的调用与我们定义的对象没有关系,他们的使用实际是直接call使用的:

所以在第一种情况下并没有发生对空指针的解引用,但第二种则是需要成员变量去完成函数运转,所以会发生对空指针的解引用,进而导致编译报错。

四,C++中struct与class的区别

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

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

相关文章

【麒麟】多种方法修改MAC地址

原文链接&#xff1a;【麒麟】多种方法修改MAC地址 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在麒麟桌面操作系统上多种方法修改MAC地址的文章。MAC地址是网络接口卡的物理地址&#xff0c;有时我们需要修改它以实现特定的网络配置需求。本文将详细介绍几种…

VS2022中打印中文乱码

我们在使用VS编写C语言代码的时候&#xff0c;我们可能遇见用printf打印中文出现乱码的情况&#xff0c;如下&#xff1a; 下面我们来讲一下怎么解决这种问题&#xff1a; 出现这种现象是因为你使用的编码设置不对&#xff1b; 1.我们首先打开文件标签&#xff0c;看看是否有…

为什么我要从测试经理转行到产品经理?

本文来聊一下我转产品经理的心路历程。 我从大学毕业做的就是软件测试&#xff0c;简单点说就是把别人设计的产品别人码的代码 我们或手工或自动化 的方式检查是否有逻辑问题&#xff0c;是否符合需求设计。某一天我突然对自己的工作不那么热爱&#xff0c;难道一辈子就干这个…

C4D学习笔记

C4D学习笔记 技巧使用对称面的两边会有问题&#xff0c;很生硬洗面奶瓶盖凹槽洗面奶瓶子尾部接缝 常用功能在一个线创建一个平面在圆面内家一圈线&#xff08;KL循环切割&#xff09;在某个面向内加一圈线某个模式切换&#xff0c;选中所有(按着Ctrl键&#xff09;焊接&#xf…

Apache OFBiz系统ProgramExport接口存在远程命令执行漏洞CVE-2024-38856 附POC

@[toc] 免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。 1. Apache OFBiz系统简介 微信公众号搜索:南…

8月6日笔记

8月6日 红日靶场打靶继续 SHOW VARIABLES #用于显示服务器运行时的各种系统变量的当前设置。这些变量可以控制服务器的行为在 MySQL 中&#xff0c;general_log 和 general_log_file 是两个与“general”相关的系统变量&#xff0c;它们控制着服务器是否启用一般查询日志以及…

安卓应用开发学习:聚合数据API获取天气预报

一、引言 上个月我通过腾讯位置服务&#xff0c;实现了手机定位应用的开发学习。最近在看软件书籍时&#xff0c;又看到了聚合数据API方面的内容。 书上介绍了聚合数据天气预报API的应用&#xff0c;不过书上的代码看得有些难受&#xff0c;我到聚合数据官网&#xff0c;对天气…

使用Streamlit构建一个web模拟HTTP请求工具

目录 前言 HTTP工具功能点&#xff1a; 1. 导入库: 2.设置页面配置: 3. Markdown格式的说明文本: 4.用户输入界面: 5. 发送请求按钮和逻辑: 6.发送HTTP请求并计算请求细节: 7.总结 前言 最初就是因为在微信看到一篇文章中,看到此http工具的制作因为觉得Streamlit有无限…

第四周:网络应用(下)

一、P2P应用_原理与文件分发 1、纯P2P架构 2、文件分发&#xff1a;客户机/服务器架构 3、文件分发&#xff1a;P2P架构 P2P和CS架构对比&#xff1a; 对于文件分发这类应用来说&#xff0c;P2P架构有着非常好的可扩展性&#xff0c;即当节点数目增大的时候&#xff0c;它所…

Ajax-02

一.form-serialize插件 作用&#xff1a;快速收集表单元素的值 const form document.querySelector(.example-form) const data serialize(form,{hash:true,empty:true}) *参数1&#xff1a;要获取哪个表单的数据 表单元素设置name属性&#xff0c;值会作为对象的属性名 建议…

【初阶数据结构题目】13.环形链表II

环形链表II 点击链接做题 思路&#xff1a;快慢指针 快慢指针&#xff0c;即慢指针一次走一步&#xff0c;快指针一次走两步&#xff0c;两个指针从链表起始位置开始运行&#xff0c;如果链表带环则一定会在环中相遇&#xff0c;否则快指针率先走到链表的未尾 让一个指针从链表…

visual studio跳转到上一个/下一个光标处的快捷键设置

vscode能通过Alt左右箭头跳转到上/下一个光标处&#xff0c;这对于“点进函数看源码&#xff0c;看完后跳转到原来位置”是非常方便的。 在Visual Studio中&#xff0c;有2种方法实现这样的功能。 第一种&#xff0c;直接点击这两个按钮&#xff1a;&#xff08;缺点是每次要用…

阻抗?关于双绞线阻抗的那些事...

双绞线的阻抗不是电阻&#xff0c;而是描述传输高频信号时电磁感应分布特性的一个特性参数。 电缆中的每个微分段的电阻、电容、电感的分布感应值都是不一样。 分析方法&#xff1a;计算每个微分电缆段的感应值分布函数&#xff0c;换算成四端网络参数等效值&#xff0c;单位…

【C语言】预处理详解(下)

文章目录 前言6. 宏和函数的对比7. #和##7.1 #运算符7.2 ##运算符&#xff08;运用较少&#xff0c;了解即可&#xff09; 8. 命名的约定9. #undef &#xff08;了解即可&#xff09;10. 条件编译&#xff08;重点&#xff09;11. 头文件的包含11.1 头文件被包含的方式&#xf…

<数据集>柑橘缺陷识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;1290张 标注数量(xml文件个数)&#xff1a;1290 标注数量(txt文件个数)&#xff1a;1290 标注类别数&#xff1a;4 标注类别名称&#xff1a;[Orange-Green-Black-Spot, Orange-Black-Spot, Orange-Canker, Orange…

CTFHUB | web进阶 | PHP | Bypass disable_function | Apache Mod CGI

开启题目 点击重置 backdoor 目录&#xff0c;再点击 GetFlag&#xff0c;然后发现了可以蚁剑连接&#xff0c; 连接成功发现无任何发现&#xff0c;所以我们使用 apache_mode_cgi插件 发现直接进入终端了&#xff0c;最后发现了 flag

深入解析Python内省之dir、getattr、hasattr和setattr使用详解

概要 内省(Introspection)是编程语言的一种能力,使程序能够在运行时检查对象的类型、属性和方法。Python提供了强大的内省工具,允许开发者动态地检查和操作对象的属性和方法。本文将详细介绍Python中的内省工具:dir、getattr、hasattr和setattr,并通过具体的示例代码展示…

springboot 股票资产管理系统-计算机毕业设计源码96208

摘要 随着全球金融市场的快速发展&#xff0c;股票交易和投资已经成为重要的经济活动之一。在此背景下&#xff0c;股票资产管理系统的设计与实现显得尤为重要。Spring Boot框架&#xff0c;以其快速、简洁和高效的特性&#xff0c;在股票资产管理系统的开发中得到了广泛应用。…

C++第三十二弹---从概念到实践:全面解析C++多态性

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1. 多态的概念 1.1 概念 2. 多态的定义及实现 2.1 多态的构成条件 2.2 虚函数 2.3 虚函数的重写 2.4 C11 override 和 final 2.5 重载、覆…

【Linux】安装部署docker及docker-compose

环境说明 操作系统&#xff1a;Ubuntu 22.04 架构&#xff1a;x86_64 一、docker安装 1.下载docker源码包 下载地址&#xff1a;https://download.docker.com/linux/static/stable/x86_64/ 注意&#xff1a;如果这个地址互联网打不开&#xff0c;那就开代理访问&#xff…