如何:使类型安全集合

本文说明如何创建自己的数据类型的类型安全的集合。主题包括:

  • 使用类型的安全基于模板的类

  • 实现 helper 函数

  • 使用非集合类

Microsoft 基础类库提供基于 C++ 模板的预定义类型安全的集合。由于它们是模板,这些类帮助提供类型安全和易用性,没有模型模拟和中为此使用非类中涉及的其他额外的工作。MFC 示例 集合 演示如何使用在 MFC 应用程序的基于模板的集合类。通常,应使用这些类,在编写新代码时收集。

使用类型的安全基于模板的类

若要使用模板基于类

  1. 声明集合类类型的变量。例如:

    CList<int, int> m_intList;
    
  2. 调用对象的成员函数。例如:

    m_intList.AddTail(100);
    m_intList.RemoveAll();
    
  3. 如果需要,请实现 helper 函数SerializeElements。有关实现这些功能的信息,请参见 实现 helper 函数。

此示例演示整数列表的说明。在步骤 1 中的第一个参数是作为列表的元素存储的数据类型。第二个参数指定该数据如何将传递给和从集合类的成员函数返回,例如 添加GetAt

实现 helper 函数

基于模板的集合类 CArrayCList以及可自定义根据需要为派生的集合类的 CMap 使用五全局 helper 函数。有关这些帮助器函数的信息,请参见 MFC 引用 中的 集合类帮助器。序列化功能的实现是必需的。对于基于模板的集合类的大多数使用。

6s70zdb8.collapse_all(zh-cn,VS.110).gif序列化元素

CArrayCListCMap 类从存档调用 SerializeElements 存储集合元素或读取它们。

SerializeElements helper 函数的默认实现执行按位 XOR 运算从存档到存档或按位读取的对象写入对象,具体取决于是否存储对象或从存档检索。,如果此事件不合适,请重写 SerializeElements

如果集合中存储从 CObject 派生的对象,并在集合元素类的实现使用 IMPLEMENT_SERIAL 宏,可以利用序列化功能内置 CArchiveCObject:

CArray< CPerson, CPerson& > personArray;

template <> void AFXAPI SerializeElements <CPerson> (CArchive& ar, 
   CPerson* pNewPersons, INT_PTR nCount)
{
   for (int i = 0; i < nCount; i++, pNewPersons++)
   {
      // Serialize each CPerson object
      pNewPersons->Serialize(ar);
   }
}

CArchive 的重载插入运算符调用 CObject::Serialize (或该功能重写) 每 CPerson 对象的。

使用非集合类

MFC 还支持集合类介绍在 MFC 1.0 版。这些类不基于模板。它们可用于包含支持的类型 CObject*UINTDWORDCString的数据。可以使用这些预定义集合 (例如 CObList) 保存从 CObject派生的任何对象的集合。MFC 还提供其他预定义集合保存原始类型 (如 UINT 和无效的指针 (void*)。但是,通常,定义自己类型安全集合保存更具体的类及其派生对象的对象通常很有用。请注意使用基于模板的类,因此对不基于模板的集合类是更多工作比。

有两种方式非集合创建类型安全的集合:

  1. 使用非集合,如果类型如果需要,转换。这是更简单的方法。

  2. 从派生并扩展的非类型安全的集合。

使用类型强制转换的非集合

  • 使用之一的非类,如 CWordArray,直接。

    例如,可以创建 CWordArray 并添加所有 32 位值到它,然后检索。nothing。您使用预定义的函数。

    还可以使用预定义集合,如 CObList,保存所有对象从 CObject派生。CObList 集合定义存储指针到 CObject。当您从列表中检索对象,则可能必须将结果强制转换为适当的类型,因为 CObList 函数返回指向 CObject。例如,因此,如果在 CObList 集合存储 CPerson 对象,则必须将检索的元素是指向 CPerson 对象。下面的示例使用 CObList 集合保存 CPerson 对象:

    CPerson* p1 = new CPerson();
    CObList myList;
    
    myList.AddHead(p1);   // No cast needed
    CPerson* p2 = (CPerson*)myList.GetHead();
    

    此方法根据需要使用预定义的集合类型和转换可能是满足许多您的集合需要。如果需要其他功能或多个类型安全,请使用基于模板的类或请按照下面步骤操作。

派生和扩展的非类型安全集合

  • 从某个预定义的非类派生您的集合类。

    当派生您的类时,可以将类型安全的包装函数提供了类型安全的接口使现有的功能。

    例如,因此,如果从 CObList 派生一个列表保存 CPerson 对象,可以添加包装函数 AddHeadPerson 和 GetHeadPerson,如下所示。

    class CPersonList : public CObList
    {
    public:
        void AddHeadPerson( CPerson* person )
            {AddHead( person );}
    
        const CPerson* GetHeadPerson()
            {return (CPerson*)GetHead();}
    };
    

    这些包装函数提供类型安全的方式添加,然后从派生的检索 CPerson 对象列表。您可以查看已为 GetHeadPerson 功能,则封装该类型强制转换。

    您可以通过定义扩展集合的函数而不是包装在类型安全包装的现有功能的新功能或添加新功能。例如,文章 删除在 CObject 集合中的任何对象 描述一个函数删除列表中包含的所有对象。此功能可添加到派生类作为成员函数。

请参见

概念

集合