动态数组进行对象管理

使用数组(或者动态数组)完成一个简单的学生信息管理系统 使用数组(或者动态数组)完成一个简单的学生信息管理系统,要求包含学生添加,删除,查询,修改等功能;学生信息包含: 学号 姓名 性别 专业 年龄 成绩 首先创建一个学生类 package Exp; public class Student { private int sno; private String name; private String sex; priva... 阅读详情

一个简单的对象管理类,管理对象的指针,使用了动态数组,可以动态扩容。


一.对象类


.h

/*!
 * \file Obj.h
 *
 * \author puppet_master
 * \date 八月 2015
 *
 * \对象类,有id,name两个属性
 */

#include "stdafx.h"
#pragma once
class CObj
{
public:
	CObj(string name);
	virtual ~CObj(void);

	//获得或者设置对象属性的方法

	void SetID(int id)
	{
		m_iObjId = id;
	}

	int GetID()
	{
		return m_iObjId;
	}

	void SetName(string name)
	{
		m_szObjName = name;
	}

	string GetName()
	{
		return m_szObjName;
	}

	//对象Tick
	virtual void Tick();

private:	
	int m_iObjId;			//对象ID
	string m_szObjName;		//对象名称
};

.cpp

#include "stdafx.h"
#include "Obj.h"

//在初始化列表中,对象的默认ID为INVALIDID,表示不可用,在进入对象管理器后,才会给分配真正的ID
CObj::CObj(string name) 
	: m_iObjId(INVALIDID),m_szObjName(name)
{

}


CObj::~CObj(void)
{
	cout<<"Obj "<<m_iObjId<<" is destructed!"<<endl;
}

void CObj::Tick()
{
	cout<<"Obj "<<m_iObjId<<" Tick"<<endl;
}


二.对象管理类

.h

/*!
 * \file ObjManager.h
 *
 * \author puppet_master
 * \date 八月 2015
 *
 *  \对象管理类,使用动态数组进行管理,木有用vector
 */

#pragma once
#include "Obj.h"

class CObjManager
{
private:	
	const int DEFAULTSIZE;				//默认大小
	int m_iMaxSize;						//当前最大对象个数
	int m_iObjCount;					//对象个数
	CObj** m_ppObjArray;				//管理对象指针的数组,这里是指针的指针

public:
	CObjManager(void);
	virtual ~CObjManager(void);

	//初始化对象管理类,给出初始时的对象数组大小
	void Init(int maxSize);

	//添加对象,如果成功,返回对象id,否则返回INVALIDID(-1)
	int AddObj(CObj* obj);

	//根据对象ID删除对象(从对象管理器中清除对象,并释放内存)
	bool DeleteObjById(int id);

	//根据对象指针删除对象(从对象管理器中清除对象,并释放内存)
	bool DeleteObjByPoint(CObj* obj);

	//根据对象ID获得对象,有的话返回对象指针,否则返回NULL
	CObj* GetObjById(int id);

	//根据对象名字获得对象,有的话返回对象指针,否则返回NULL
	CObj* GetObjByName(string name);

	//遍历对象,并调用对象方法
	virtual void Tick();

	//删除所有对象
	void RemoveAllObj();

	//当数组不够大时,进行动态扩展操作
	bool ExtendBuffer(int newSize);

	//获得当前对象个数
	int GetObjCount()
	{
		return m_iObjCount;
	}
};
.cpp

#include "stdafx.h"
#include "ObjManager.h"


CObjManager::CObjManager(void):
	DEFAULTSIZE(10), m_iObjCount(0), m_iMaxSize(DEFAULTSIZE), m_ppObjArray(NULL)
{
}


CObjManager::~CObjManager(void)
{
}

void CObjManager::Init(int maxSize)
{
	//动态申请一个对象数组
	m_ppObjArray = new CObj*[maxSize];
	m_iMaxSize = maxSize;
	//打印Log
	if (m_ppObjArray)
		cout<<"CObjManager Init OK"<<endl;
	else
		cout<<"CObjManager Init Failed"<<endl;
}

int CObjManager::AddObj(CObj* obj)
{

	if (!obj)
		return INVALIDID;
	//如果不够大了,先动态扩展内存
	if (m_iObjCount >= m_iMaxSize)
	{
		//动态将buffer扩展为两倍,扩展失败,直接返回非法ID
		if (!ExtendBuffer(m_iMaxSize * 2))
			return INVALIDID;
	}

	//直接将新建的对象ID设置为当前对象个数,然后对象个数+1
	m_ppObjArray[m_iObjCount] = obj;
	obj->SetID(m_iObjCount);
	m_iObjCount++;

	return m_iObjCount - 1;
}

bool CObjManager::DeleteObjById(int id)
{
	if (id > m_iObjCount)
		return false;

	//交换数组中最后一个对象与被删除对象的位置
	m_iObjCount--;
	swap(m_ppObjArray[id],m_ppObjArray[m_iObjCount]);
	m_ppObjArray[id]->SetID(id);

	//清除最后一个对象(delete内存,并且指针置空)
	SAFE_DELETE(m_ppObjArray[m_iObjCount]);

	return true;
}

bool CObjManager::DeleteObjByPoint(CObj* obj)
{
	int id = obj->GetID();
	return DeleteObjById(id);
}

CObj* CObjManager::GetObjById(int id)
{
	if (id > m_iObjCount)
		return NULL;
	return m_ppObjArray[id];
}

CObj* CObjManager::GetObjByName(string name)
{
	for (int i = 0; i < m_iObjCount; i++)
	{
		if (m_ppObjArray[i]->GetName() == name)
			return m_ppObjArray[i];
	}
	return NULL;
}

void CObjManager::RemoveAllObj()
{
	for (int i = 0; i < m_iMaxSize; i++)
	{
		SAFE_DELETE(m_ppObjArray[i]);
	}
	SAFE_DELETE_ARRAY(m_ppObjArray);

	m_iObjCount = 0;
}

void CObjManager::Tick()
{
	for (int i = 0; i < m_iObjCount; i++)
	{
		m_ppObjArray[i]->Tick();
	}
}

bool CObjManager::ExtendBuffer(int newSize)
{
	//申请一个临时的指针指向原来的内存区域
	CObj** ppTempBuffer = m_ppObjArray;
	//申请一块新的更大的内存
	m_ppObjArray = new CObj*[newSize];
	//将原来的内存区域的内容拷贝到新的内存区域,由于管理的仅仅为对象指针,所以并不会有多大
	if (ppTempBuffer)
	{
		memcpy(m_ppObjArray, ppTempBuffer, sizeof(CObj*) * m_iMaxSize);
	}
	//将多余区域置空
	memset(&(m_ppObjArray[m_iObjCount]), 0, sizeof(CObj*) * (newSize - m_iMaxSize));
	m_iMaxSize = newSize;

	//清除原来的内存区域
	SAFE_DELETE_ARRAY(ppTempBuffer);

	return true;
}



三.使用对象管理类

stdafx

// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//

#pragma once

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <string>
using namespace std;

//定义一个不可用的ID,作为错误编号
#define INVALIDID -9999

//定义安全删除宏
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) if((p) != NULL) {delete(p); (p) = NULL;}
#endif

//定义安全删除数组的宏
#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) if ((p) != NULL) {delete[] (p); (p) = NULL;}
#endif


// TODO: 在此处引用程序需要的其他头文件


main


/*!
 * \file GameTest.cpp
 *
 * \author puppet_master
 * \date 八月 2015
 *
 * \name 一个很好的使用原生数组管理对象的实例
 * \point 动态数组,增加删除实例操作时间空间复杂度均为最小
   \由于管理的均为对象的指针,管理较为方便,并且仅在大小不够时候才进行动态扩展
 */

#include "stdafx.h"
#include "Obj.h"
#include "ObjManager.h"

int _tmain(int argc, _TCHAR* argv[])
{
	CObjManager* p_Manager = new CObjManager();
	//初始化大小为5
	p_Manager->Init(5);

	//先插入20个对象
	CObj* pObj = NULL;
	for(int i = 0; i < 20; i++)
	{
		pObj = new CObj("HEHEH");
		p_Manager->AddObj(pObj);
	}

	//查看Manager内存储对象
	cout<<p_Manager->GetObjCount()<<endl;
	p_Manager->Tick();

	//删除ID为0的对象,查看对象个数
	p_Manager->DeleteObjById(0);
	cout<<p_Manager->GetObjCount()<<endl;
	
	//增加一个对象,查看Manager对象
	p_Manager->AddObj(new CObj("HAHAAH"));
	cout<<p_Manager->GetObjCount()<<endl;
	p_Manager->Tick();

	//移除所有的对象,查看Manager对象
	p_Manager->RemoveAllObj();
	cout<<p_Manager->GetObjCount()<<endl;
	p_Manager->Tick();

	int i;
	cin>>i;



	return 0;
}


好吧,贴代码没啥意思。其实就是一个简单的练习,动态数组的使用。感觉这种实现有几个地方还是比较巧妙的。
1.主要的思想就是对象本身原本没有ID,仅有名字。然后,在对象被放在动态数组的时候,采用当前数组的元素个数作为新加入的对象的ID(数组索引永远比个数少1),然后将这个ID反注册给对象本身,这样,对象的ID就和它在对象管理器的数组中的ID是一致的。
2.对象管理类管理的并非对象本身,而是对象的指针,这样操作的话也比较方便。
3.可以动态扩容,在初始化的时候给管理类一个初始的大小,作为最开始动态数组的大小。当大小不够的时候,会重新申请一个2倍于原来大小的动态数组,然后将原来数组中的内容全部拷贝到新的数组中,再清除原来的数组。由于我们操作的是对象的指针,所以并不会太消耗性能,并且动态扩容的操作也不会经常触发的。
4.感觉最巧妙的就是删除对象的时候,将被删除对象的指针和当前数组最后一个对象指针位置互换,这时,ID位置的对象就变成了原本最后一个对象了,然后将这个ID再重新注册给对象。最后,再删除最后一个指针所指的对象,即我们要删除的那个对象。这样做的话,删除对象的时间复杂度是O(1)。
5.提供了根据名字查询对象的接口以及根据对象本身指针来从对象管理器中删除对象接口。




C++创建类对象方法和动态对象数组 最近在学C++,在内存管理这里遇到几个点,记录一下加深记忆。 创建类对象的方法 C++中有两种创建对象的方法,一种是直接声明,另一种则是使用new关键字,虽然作用相同,但是它们底层的存储方式却完全不同。在此之前,我们先了解一下C++程序的存储形式。 C++程序的内存格局通常分为四个区: 1. data area(全局数据区) 2. code area (代码区) 3. stack area (... 阅读详情

相关推荐

直流无刷减速电机选型指南:从KV值到霍尔传感器,新手必看的5个关键参数

本文详细解析直流无刷减速电机选型的5个关键参数,包括KV值、转矩、电流与功率、减速比选择以及霍尔传感器配置。通过实战案例和避坑策略,帮助工程师精准匹配电机性能与负载需求,提升工业自动化设备的可靠性和效率。特别强调霍尔传感器在精准控制中的关键作用。

alice7model的博客 620

动态空间管理

定义数组时,占用静态分配单元,数组大小在编译阶段就确定了,而实际应用中又经常需要在程序运行期间才确定数组大小,这就需要动态分配函数malloc和calloc,从内存空间中的堆中获取动态空间,建立动态数组。(在C#中不用这么麻烦啦,一个List类就解决问题)       void* malloc(unsigned size);//按字节数size分配内存空间,返回空间起始地址。       vo

遥远的她 747

保姆级教程:用PCAN-View监控汽车CAN总线,从硬件连接到报文分析(附快捷键大全)

本文提供了一份详细的PCAN-View使用教程,涵盖从硬件连接到报文分析的全流程,特别适合汽车电子工程师和初学者。内容包括硬件准备、软件安装、核心功能操作、高级技巧及故障排查,并附有实用的快捷键大全,帮助用户高效监控和分析CAN总线数据。

weixin_42542669的博客 497

C与C++中动态数组的生成及内存动态管理

C中动态数组的生成及释放: #include #include #include void main() {     int *array = 0, num, i;    printf("please input the number of element: ");    scanf("%d", &num);    // 申请动态数组使用的内存块    array

1164

ANSYS APDL生死单元实战:焊接模拟从入门到精通(附完整命令流)

本文详细介绍了使用ANSYS APDL进行焊接模拟的核心技术——生死单元法。通过一个完整的平板对接焊案例,从原理剖析、模型搭建、命令流编写到移动热源施加和后处理,手把手指导工程师掌握这一动态仿真方法,有效预测焊接过程中的温度场、残余应力与变形。

k6l7m8n9的博客 150

增量编码器资讯大全

增量编码器是什么 增量式编码器是将位移转换成周期性的电信号,再把这个电信号转变成计数脉冲,用脉冲的个数表示位移的大小,按照工作原理编码器可分为增量式和绝对式两类。 增量式编码器是将位移转换成周期性的电信号,再把这个电信号转变成计数脉冲,用脉冲的个数表示位移的大小。 编码器是把角位移或直线位移转换成电信号的一种装置。前者称为码盘,后者称码尺.按照读出方式编码器可以分为接触式和非接触式两种.接触式采...

kindele的博客 6008

使用指针数组来处理对象时的问题

气死了!!! 同学一直问我cin无法输入对象类型指针数组里的数据怎么办 我看了好久cin的结束判定和缓存清空后 结果这娃子的程序指针数组没有指向对象!!!! 气死偶了 记得对象类型指针数组一定要指向实际的对象才能操作里面的数据呀!实例都没有哪里会有这个成员的储存空间嘛 气死了气死了气死了 ...

qq_45772415的博客 184

【OpenClaw从入门到精通】第73篇:30天OpenClaw实战挑战——从零搭建个人数字助理(Day15-21)万字超详细高阶实战版

经过前两周的基础部署与功能搭建,你已拥有可自动化干活的AI助理与数字员工团队,但距离“高阶精通”仍有差距。本文聚焦第三周(Day15-21)核心实战,围绕安全审计、语音能力接入、Token成本控制、Agent Loop优化、One-Liner指令五大核心模块,结合真实落地案例与踩坑经验,提供超详细实操指南。通过本文,你将掌握生产级安全加固方案、语音交互全流程配置、低成本高性价比使用策略、Agent自主闭环优化技巧,以及一句话搞定复杂任务的高效指令用法,同时完成中期复盘与最后九天冲刺规划

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 360

智能指针管理通过new创建的对象

来自《编写高质量代码:改善C++程序的150个建议》读书笔记

zuolj的专栏 2649

【DaVinci Developer专题】-36-创建一个“既读又写”的Sender Receiver Port(SR PR-Port)

有时会遇到SWC需要对一个Port进行“既可以读,也可以写”的操作。以下图为例,Test_A_SWC中Test_A_Port是P-Port;Test_B_SWC中Test_A_Port是R-Port。Test_C_SWC需要对Test_A_Port同时进行“读”和“写”。 该篇将详细介绍PR-Port的创建方法。 目录 1 创建一个S/R Port Interface 2 将一个PR-Port端口添加至Application Component 3 PR-Port端口初始化 4 Run.

「汽车电子助手」的博客 3013

基于STM32F103C8T6的智能蓝牙手环系统设计与实现

摘要:本文设计并实现了一款基于STM32F103C8T6单片机的智能蓝牙手环系统。该系统集成了ADXL345加速度计、DS18B20温度传感器、plusesennor心率模块和BT06蓝牙模块,实现了心率(±2bpm)、体温(±0.5℃)、步数(±3%)等健康数据的实时监测与显示。通过OLED屏提供人机交互界面,支持蓝牙APP远程控制,具备自动步数清零、异常提醒等功能。测试表明系统各项功能均达到设计要求,响应时间0.1-0.5秒,心率检测准确率98%,体温检测准确率99%,功耗50mA(工作)/10mA(待

3254968421的博客 205

用动态的对象数组类构建学生管理系统

这是类的成员组成,在私有成员中,s是一种结构体指针,size代表学生管理系统的容量(可以调整),count代表计入的学生的数量。在公有成员是一些函数,用来做一些对系统的操作。我预先准备好的数据有215名同学的信息,因此我将容量从默认容量50更改为了500。更改系统容量,考虑到要录入的成绩的数量无法预测,因此在使用前先更改容量。3.由于输出的人数过多,想要唤回菜单比较麻烦,所以可以唤回菜单。两图分别是传入的文件和传出的文件。

hugecanaan的博客 712

【C语言趣味教程】(0) 专栏介绍

这是一套C 语言趣味教学专栏,目前正在火热连载中,欢迎猛戳订阅!本专栏保证篇篇精品,继续保持本人一贯的幽默式写作风格,当然,在有趣的同时也同样会保证文章的质量,旨在能够产出"有趣的干货" !本系列教程不管是零基础还是有基础的读者都可以阅读,可以先看看目录!标题前带星号 (*) 的部分不建议初学者阅读,因为内容难免会超出当前章节的知识点,面向的是对 C 语言有一定基础或已经学过

有道无术, 术尚可求。有术无道, 止于术。 2万+

【Java数据结构与算法】动态数组、线性表、数组、动态数组、动态数组接口设计、清除所有元素、添加元素、 删除元素、清空数组、是否包含某个元素、扩容、打印数组、泛型、对象数组、内存管理细节、动态数组源码

【Java动态数组】线性表、数组(Array)、动态数组(Dynamic Array)、动态数组接口设计、清除所有元素 - clear()、添加元素 - add(E element)、add(int index, E element)、 删除元素 - remove(int index)、是否包含某个元素 - contains(E element)、清空数组 - clear()、清空数组、扩容 - ensureCapacity(int capacity)、打印数组、泛型、对象数组、内存管理细节、动态数组源码

愿你怀着最初的梦走最艰难的路 853

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

java基础之动态对象数组[19]

java基础之动态对象数组[19]

FlymaAqi,芜湖,飞马阿起,passion!passion! 335

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

c++ 动态数组类的创建和简单运用

#include&lt;iostream&gt; #include&lt;cassert&gt; using namespace std; class Point{ public: Point(int x,int y):x(x),y(y){ cout&lt;&lt;"调用构造函数"&lt;&lt;endl; } Point():x(0),y(0){ cout&lt;&lt;"调用默认构造函.

qq_41814721的博客 5369

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

【Java随笔】对象数组、动态数组:自动扩容、删除

锈太厚,只能说加油,铁子

weixin_35695688的博客 283

对象数组

package test11; import java.util.Arrays; public class ObjectArrays{ public static void main(String[] args) { chickenManage cs=new chickenManage(5); cs.add(new chicken(1,"小1",3)); cs.add(ne...

qq_33834446的博客 184

面向【动态数组对象】之远哥学生管理系统

package cn.kgc.tyl.test0930.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * */ @Data @NoArgsConstructor @AllArgsConstructor public class Student { private int id; private String name; } package cn.kg

m0_45442261的博客 187

java之对象数组与管理

对象数组就是数组里的每个元素都是类的对象,赋值时先定义对象,然后将对象直接赋值给数组。 示例: Chicken[] cs = new Chicken[10]; 使用对象数组实现多个Chicken的管理。 动态数组: 1、数组是一种线性数据结构。 2、数组不适合做删除、插入等操作,适合添加、查找、遍历。 示例: import java.util.Arrays; public class Demo {...

weixin_43973189的博客 358

C++ Primer 创建动态数组

动态分配的数组不必在编译时知道其长度,可以在运行时才确定数组长度。与数组变量不同,动态分配的数组将一直存在,直到程序显示释放它。 每一个程序在执行时都占用一块可用的内存空间,用于存放动态分配的对象,此内存空间称为程序的自由存储区或堆。C语言使用一对标准库函数malloc和free分配存储空间,而C++则使用new和delete 。 1.动态数组的定义 int *pia=new int[10]

等待花开1991的专栏 1340

共享内存中动态数组_算法与数据结构(线性结构-动态数组)

在上一节中我们已经实现了动态数组的实现,这节我们来完善动态数组。1.将只适用于整数类型的动态数组变为任意对象适用 private int elements[]; public DynamicArray(int capacity){ ram = (ram > DEFAULT_SIZE) ? ram:DEFAULT_SIZE; elements = new i...

weixin_39995351的博客 226

C++ 动态数组

C++语言和标准库提供了两种一次分配一个对象数组的方法。C++语言定义了另一种new表达式语法,可以分配并初始化一个对象数组。标准库中包含一个名为allocator的类,允许我们将分配和初始化分离。使用allocator通常会提供更好的性能和更灵活的内存管理能力。 new和数组 为了让new分配一个对象数组,我们要在类型名之后跟一对方括号,在其中指明要分配的对象的数目。在下例中,new分配要求数量的对象并(假定分配成功后)返回指向第一个对象的指针: int get_size_new() { ret

恋恋风辰的技术博客 1万+

Java从入门到精通—数组【对象数组】

对象数组的缺陷:长度是固定的; 对象数组的优势:数据线性访问,根据索引访问,速度较快(时间复杂度为“1”)

Da_Xiong的博客 382

C++对象数组&对象指针&对象指针数组

函数返回类型名 (类名∷*函数指针变量名)(参数表列);

pl0020的博客 764

C++作业 请设计一个程序实现图书库存的管理(动态数组类/Vector类)

【问题描述】 请设计一个程序实现图书库存的管理。请根据给定的main函数及程序输出,完成设计。具体要求如下。 一、请设计一个Book类: 1、包括私有成员: unsigned int m_ID;//编号 string m_Name;//书名 string m_Introductio//简介 string m_Author;//作者 string m_Date;//日期 unsigned int m_Page;//页数 2、设计所有成员变量的getter和setter函数,关于getter和set

m0_45834939的博客 824
上一篇: .dll,.lib,.def 和 .exp文件
下一篇: VS中一些配置的总结
puppet_master
puppet_master 领域专家: C/C++技术领域 领域专家: C/C++技术领域
博客等级 码龄12年 2695粉丝 161原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值