C++ 中的 Java 风格向量类






3.76/5 (21投票s)
2002年12月18日
4分钟阅读

151037

654
关于类型指针的 vector 集合类的介绍。
引言
本文将向您介绍一个 C++ 类,该类用于存储和管理一系列类型指针。它的目的是轻松地管理具有熟悉的 Java 风格接口的对象指针集合。本文是我计划发布的几篇系列文章的第一篇,将介绍和分享我多年来广泛使用的一些有用的实现。
背景
在 MFC 之前,存储和管理对象指针集合在我开发的软件中被广泛使用。这些软件不是为 MFC 编写的,因此 MFC 集合对象不可用。我可以使用 STL,但设计标准阻止我使用此类模板。因此,创建了一个旨在提供此支持的类,并将其用于应用程序开发。随着时间的推移,其设计不断被添加和修剪,以保留类中的最佳功能。当涉及到 Java 项目时,我被其清晰的接口以及其类和方法命名方法所吸引。如果有什么我不喜欢的,那就是晦涩难懂、令人费解的代码。分享代码的意义何在,如果光是整理代码就会让人头疼?这有点像读一本枯燥的物理书。
我决定将这种方法应用到我目前使用的支持类集合中,而这就是其中一项努力的结果。
为什么不使用 STL?
为了清晰起见,我们必须开发可以被一个客户端(客户)在 Java 中使用,另一个客户端(客户)在 MFC 中使用的软件模块(源代码)。这意味着并行开发,并且不能使用 STL,所以我们需要一组 C++ 核心类,使其尽可能类似于 Java,从而使过渡更容易并节省成本。
ZVector 类
顾名思义,vector 类是一个 vector 列表管理器,它模仿了 Java 的大部分外观和感觉。类名前面有一个简单的“Z”前缀,以防止命名空间冲突。在功能上,它能够处理与 CTypePtrArray
常用的相同问题。主要区别在于,它通过类 Java 风格的接口更容易阅读和使用。另一个区别是,它是用纯 C++ 编写的,不依赖于操作系统或 Windows API(stdafx.h 是可选的)。因此,它应该可以移植到任何操作系统。(我说“应该”,因为我实际上并没有在其他操作系统上使用过它)。这个类不是很大,这就是关键。保持简单。
解决方案
我的解决方案方法很简单。首先,创建了一个类来管理类型中性指针的操作。这些指针可以是指向用户期望的任何类型的指针。其主要目的是为 vector 列表提供内存分配和内存访问功能。它还优化了这些过程,以减少不必要的重新分配,从而提高速度。此外,它像其 Java 对应物一样,非常谨慎地跟踪对象。
这是 vector 管理器类
class ZS_EXPORT ZVectorBuffer { //---------------------------------- // Instance variables //---------------------------------- private: static Ptr pNull; //---------------------------------- // Instance variables //---------------------------------- protected: Ptr * pPtr; int iDataCount; int iDataCapacity; int iDataIncrement; //---------------------------------- // Constructor/Destructor //---------------------------------- private: ZVectorBuffer(const ZVectorBuffer &array); public: ZVectorBuffer(int initial=0,int increment=8); ~ZVectorBuffer(); //---------------------------------- // Instance methods //---------------------------------- private: void operator = (const ZVectorBuffer &that); bool move(int from_index, int to_index); public: void ensureCapacity(int elements); void setSize(int size); int size() const; int capacity() const; int indexOf(CPtr ptr,int start=0) const; bool contains(CPtr ptr) const; bool isEmpty() const; void copy(const ZVectorBuffer &that); void append(const ZVectorBuffer &that); Ptr & getElement(int i) const; void addElement(Ptr ptr); bool mergeElement(Ptr ptr); void removeElement(Ptr ptr); void removeElementAt(int i); void removeAll(); void sort(int (*compare)(CPtr, CPtr)); bool raise (CPtr ptr); bool lower (CPtr ptr); bool toHead(CPtr ptr); bool toTail(CPtr ptr); };
您在检查此类时会注意到 char *
的简写形式 Ptr
和 const char *
的简写形式 CPtr
。这是一个 typedef
,仅用于使代码更具可读性。第二个类是您在创建这些对象时实际使用的类。它是名为 ZVector
的模板类。其目的是创建类型化列表的实例,并在使用对象时提供正确的类型转换,因此您不必这样做。下面是它
template<class T> class ZVector : public ZVectorBuffer { public: T* & elementAt(int i) const { return (T*&)getElement(i); } T* & operator [] (int i) const { return (T*&)getElement(i); } T* & firstElement() const { return (T*&)getElement(0); } T* & lastElement() const { return (T*&)getElement(iDataCount-1);} public: void operator << (T * t) { addElement(t); } void operator >> (T * t) { removeElement(t); } void setElementAt(T * t,int i) { pPtr[i] = t; } };
此类纯粹内联构造,提供了应用程序中将使用的主要运算符。如果您仔细查看,还会注意到在 vector 管理器类中安装了一个虚拟的静态指针。由于访问运算符需要指针引用,因此如果索引越界,虚拟指针将用于满足此条件。赋值此项是无害的,我宁愿这样做,也不愿在如此低的级别上引入异常。
使用 ZVector 类
最后,我将提供一些代码片段,以展示该类如何在典型应用程序中使用。
在声明中,表示方法非常简单。在类定义或代码主体中实例化一个模板对象,然后使用它。很少有人会动态创建对象,而且我从未发现有此需要。
//---------------------------------- // Instance variables //---------------------------------- private: ZVector <MyClass> vChildren;
或者...
void some_method() { ZVector<MyClass> vector; // Create a typed vector vector.addElement(new MyClass()); // Add one object vector.addElement(new MyClass()); // Add another object (unique) MyClass *object = vector[1]; // Access second object vector.removeElement(object); // Remove the second object delete object; // Delete the second object object = vector[0]; // Access first object delete object; // Delete the first object }
结论
简单但有效。它并非万无一失。如果您非常努力,您可能会打破它,但在日常使用中它是牢不可破的。在几乎所有情况下,我主要使用模板运算符,并且只使用管理器类中的几个方法。我有大约 7-10 名程序员和工程师每天都在使用它,并且没有出现任何问题。我相信它的性能非常好,尽管我还没有与其他类进行基准测试。我很乐意获得有关此的任何信息。
这是一个核心类。将来,我将展示一些以此类为基类的派生实现。它们也将包含 Java 风格的接口,使其看起来和感觉非常熟悉。