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

创建 C++ 集合类

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.11/5 (9投票s)

2004年3月9日

4分钟阅读

viewsIcon

120319

如何使用模板创建自定义集合类,并利用 C++ std::vector STL 库以及运算符。我期望您能够理解指针、类、模板和运算符的工作原理。

引言

C++ 提供了自己的 STL(标准模板库)容器(例如 std::vector)。最好使用这些容器而不是自己编写,因为 C++ 设计者们在确保性能方面付出了巨大的努力。

为什么要使用集合类?

“集合类是一种容器类,用于存储一个或多个特定类型的项”

举例来说,我想开发一个游戏,其中有一个包含 9 个按钮的棋盘。每个按钮都有一个开或关的状态。每个按钮位于棋盘上的特定 x,y 位置,并且其颜色取决于其状态以及点击该按钮的玩家。下图显示了包含九个按钮的棋盘。

图 1。

在代码方面,我将有一个包含按钮集合的棋盘类。下图显示了棋盘类的 UML 表示。

图 2。

集合类将允许我们访问每个按钮及其属性和函数(例如状态、x 和 y 位置、颜色)。

好了,开始编码吧。

代码

集合类的代码相当简单。如果您理解指针、类、模板和运算符的工作原理,那么您已经完成了 90%。剩下的就是将这些技术结合起来,“ voilà!”您就会拥有自己的集合类。

在您喜欢的 C++ 编译器中,创建一个新的 win32 项目和一个头文件。我称我的为“TCollection.h”。

然后将以下代码行添加到头文件中

#include <vector>

using namespace std;
//This simply includes the vector container from the STL.

//Next we create the template class:

template <class TBase>class TCollection{
};

创建模板类后,我们首先添加受保护的 vector 成员。设置为受保护是因为我们希望派生自集合类的类能够访问该成员。

template <class TBase>
class TCollection
{
  protected:
  //The Vector container that will hold the collection of Items

  vector<TBase> m_items;
};

基本上,我们需要对我们的容器执行三件事:添加项、删除项和清空容器。我们还想知道容器中有多少项,为此我们将需要一个 Count() 函数。所有这些函数都将是公共的。

Add() 函数

由于我们已经知道要将 TBase 类型的项添加到容器中,因此我们只需声明并定义一个 Add() 函数。

int Add(void) 
{
  //Create a new base item

  TBase BaseItem; 
  //Add the item to the container

  m_items.push_back(BaseItem); 
  //Return the position of the item within the container. 

  //Zero Based

  return (m_items.size()-1); 
}

Remove() 函数

对于 Remove() 函数,我们需要声明并定义一个返回指向要删除项的指针的函数。这是因为我们的 vector 容器的 erase 函数需要一个指针才能删除一个项。

//Function to return the memory address of a specific Item

TBase* GetAddress(int ItemKey) 
{
  return &(m_items[ItemKey]);
}

始终最好进行防御性编程,但出于本文的考虑,我没有这样做,因为我想展示集合类背后的原理。例如,您可以在返回项的地址之前测试该项是否真的存在于容器中。

现在我们有了 GetAddress() 函数,我们可以继续我们的 remove 函数。

void Remove(int ItemKey) 
  //Remove a specific Item from the collection

{
  //Remove the Item using the vector’s erase function

  m_items.erase(GetAddress(ItemKey)); 
}

Clear() 函数

Clear 函数非常简单。

void Clear(void) //Clear the collection

{
  m_items.clear();
}

Count() 函数

Count 函数也非常简单。

//Return the number of items in collection

int Count(void) 
{
  return m_items.size(); //One Based

}

请注意,返回的数字是基于一的。这意味着要访问集合中的最后一个项,您需要使用 Count()-1

现在我们已经有了所有的函数,我们只需要再做一件事。我们希望通过使用 [] 方括号来访问一个项。我们通过使用运算符重载来实现这一点。

operator []

我们希望该运算符返回对我们的基项的引用。请记住,基项的类型是 TBase

//Operator Returning a reference to TBase

TBase& operator [](int ItemKey) 
{
  return m_items[ItemKey];
}

我们的集合类现在完成了。请看下面的整个文件。

头文件

//TCollection.h

#include <vector>

using namespace std;
template <class TBase> 
class TCollection
{
protected:
  //The Vector container that will hold the collection of Items

  vector<TBase> m_items;
public:
  int Add(void) 
  {
    //Create a new base item

    TBase BaseItem; 
    //Add the item to the container

    m_items.push_back(BaseItem); 
    //Return the position of the item within the container. 

    //Zero Based

    return (m_items.size()-1); 
  }
  //Function to return the memory address of a specific Item

  TBase* GetAddress(int ItemKey) 
  {
    return &(m_items[ItemKey]);
  }
  //Remove a specific Item from the collection

  void Remove(int ItemKey) 
  {
    //Remove the Item using the vector’s erase function

    m_items.erase(GetAddress(ItemKey)); 
  }
  void Clear(void) //Clear the collection

  {
    m_items.clear();
  }
  //Return the number of items in collection

  int Count(void) 
  {
    return m_items.size(); //One Based

  }
  //Operator Returning a reference to TBase

  TBase& operator [](int ItemKey) 
  {
    return m_items[ItemKey];
  }
};

测试集合类

我们通过创建一个包含我们 TCollection.h 文件的 winmain.cpp 文件来测试集合类。

#define WIN32_MEAN_AND_LEAN
//Normal win32 headers

#include <windows.h> 

#include <windowsx.h>

//---------------------

//The collection class header

#include "TCollection.h"

//The string class

#include <string>

using namespace std;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, 
  char * cmdParam, int cmdShow)
{
  TCollection<string> ColClass; //Create a collection of strings

  int i = ColClass.Add();
  ColClass[i] = "Hallo";
  MessageBox(NULL, ColClass[i].c_str(),"",MB_OK);
  return(0);
}

从上面的代码可以看出,我创建了一个新的字符串集合,添加了一个项,然后访问了该项及其属性。我们现在拥有一个可以接受任何类型的集合类。毫不费力……

举个例子,如果我将 int 作为我的集合类

char buffer[20];
TCollection<int> ColClass2;
int j = ColClass2.Add();
ColClass2[j] = 3;
sprintf(buffer,"Item %d = %d",j, ColClass2 [j]);
MessageBox(NULL,buffer,"",MB_OK);

待办事项

像本文前面所述,创建一个 CBoard CButton 类。向棋盘添加九个按钮,设置每个按钮的属性,然后循环遍历每个按钮并显示其属性。

© . All rights reserved.