Поделиться через


Практическое руководство. Создание типобезопасных коллекций

В этой статье объясняется, как создавать типобезопасные коллекции для собственных типов данных. Разделы включают:

Библиотека классов Microsoft Foundation предоставляет предопределенные типобезопасные коллекции на основе шаблонов C++ . Так как они являются шаблонами, эти классы помогают обеспечить безопасность типов и простоту использования без приведения типов и других дополнительных работ, связанных с использованием класса nontemplate для этой цели. В примере MFC COLLECT демонстрируется использование классов коллекций на основе шаблонов в приложении MFC. Как правило, используйте эти классы в любой момент, когда вы пишете новый код коллекций.

Использование классов на основе шаблонов для типа Сейф ty

Использование классов на основе шаблонов

  1. Объявите переменную типа класса коллекции. Например:

    CList<int, int> m_intList;
    
  2. Вызовите функции-члены объекта коллекции. Например:

    m_intList.AddTail(100);
    m_intList.RemoveAll();
    
  3. При необходимости реализуйте вспомогательные функции и SerializeElements. Сведения о реализации этих функций см. в разделе "Реализация вспомогательных функций".

В этом примере показано объявление списка целых чисел. Первый параметр на шаге 1 — это тип данных, хранящихся в виде элементов списка. Второй параметр указывает, как данные передаются и возвращаются из функций-членов класса коллекции, таких как Add и GetAt.

Реализация вспомогательных функций

Классы коллекций на основе шаблонов CArrayCListи CMap пять глобальных вспомогательных функций, которые можно настроить по мере необходимости для производного класса коллекции. Дополнительные сведения об этих вспомогательных функциях см. в справке по классам коллекций в справочнике по MFC. Реализация функции сериализации необходима для большинства классов коллекций на основе шаблонов.

Сериализация элементов

CListCMap Вызов CArrayи классы SerializeElements для хранения элементов коллекции в архив или их чтения из архива.

Реализация вспомогательной SerializeElements функции по умолчанию выполняет побитовую запись из объектов в архив или побитовое чтение из архива в объекты в зависимости от того, хранятся ли объекты в архиве или извлекаются из архива. Переопределите SerializeElements , если это действие не подходит.

Если коллекция хранит объекты, производные от CObject этого, и вы используете макрос в реализации класса элементов коллекции, вы можете воспользоваться IMPLEMENT_SERIAL преимуществами функций сериализации, встроенных в CArchive и CObject:

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 объекта.

Использование классов коллекции Nontemplate

MFC также поддерживает классы коллекций, представленные в MFC версии 1.0. Эти классы не основаны на шаблонах. Их можно использовать для хранения данных поддерживаемых типов CObject*, UINTDWORDи CString. Эти стандартные коллекции (например CObList) можно использовать для хранения коллекций любых объектов, производных от CObject. MFC также предоставляет другие предопределенные коллекции для хранения примитивных типов, таких как UINT и указатели void (void*). В общем случае часто бывает полезно определить собственные коллекции, безопасные для типа, для хранения объектов более конкретного класса и его производных. Обратите внимание, что это делается с классами коллекции, не основанными на шаблонах, является более работой, чем использование классов на основе шаблонов.

Существует два способа создания типобезопасных коллекций с коллекциями nontemplate:

  1. При необходимости используйте коллекции nontemplate с приведением типов. Это более простой подход.

  2. Производный от и расширяющий типобезопасную коллекцию, не относясь к типу.

Использование коллекций nontemplate с приведением типов

  1. Используйте один из нетемплатных классов, например CWordArrayнапрямую.

    Например, можно создать CWordArray и добавить в него 32-разрядные значения, а затем получить их. Больше ничего не делать. Вы просто используете предопределенные функции.

    Можно также использовать предопределенную коллекцию, например CObListдля хранения любых объектов, производных от CObject. Коллекция CObList определяется для хранения указателей CObjectна . При получении объекта из списка может потребоваться привести результат к соответствующему типу, так как CObList функции возвращают указатели CObjectна . Например, если вы храните CPerson объекты в CObList коллекции, необходимо привести извлеченный элемент, чтобы быть указателем на CPerson объект. В следующем примере для хранения CPerson объектов используется CObList коллекция:

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

    Этот метод использования предопределенного типа коллекции и приведения, как это необходимо, может быть достаточно для многих потребностей вашей коллекции. Если вам нужна дополнительная функциональность или более безопасность типов, используйте класс на основе шаблона или выполните следующую процедуру.

Наследование и расширение небезопасной коллекции типов

  1. Наследуйте собственный класс коллекции из одного из предопределенных классов, не являющихсяtemplate.

    При наследовав класс, можно добавить функции-оболочки, безопасные для типа, чтобы обеспечить типобезопасный интерфейс для существующих функций.

    Например, если вы производите список от CObList хранения CPerson объектов, можно добавить функции-оболочки AddHeadPerson и GetHeadPerson, как показано ниже.

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

    Эти функции-оболочки предоставляют безопасный способ добавления и извлечения CPerson объектов из производного списка. Вы можете увидеть, что для GetHeadPerson функции вы просто инкапсулируете приведение типов.

    Вы также можете добавить новые функции, определив новые функции, расширяющие возможности коллекции, а не просто упаковав существующие функции в типобезопасные оболочки. Например, статья об удалении всех объектов в коллекции CObject описывает функцию для удаления всех объектов, содержащихся в списке. Эту функцию можно добавить в производный класс как функцию-член.

См. также

Коллекции