65.9K
CodeProject 正在变化。 阅读更多。
Home

C++ 中的 Java 风格向量类

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.76/5 (21投票s)

2002年12月18日

4分钟阅读

viewsIcon

151037

downloadIcon

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 * 的简写形式 Ptrconst 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 风格的接口,使其看起来和感觉非常熟悉。

© . All rights reserved.