Cómo: Crear una colección con seguridad de tipos
En este artículo, se explica cómo crear colecciones con seguridad de tipos para sus propios tipos de datos. Contenido de los temas:
La biblioteca MFC (Microsoft Foundation Class) proporciona colecciones con seguridad de tipos predefinidas basadas en plantillas de C++. Dado que son plantillas, estas clases permiten proporcionar seguridad de tipos y facilidad de uso sin la conversión de tipos y otros trabajos adicionales que implica el uso de una clase que no es plantilla para este propósito. En el ejemplo de MFC COLLECT, se muestra el uso de clases de colección basadas en plantillas en una aplicación MFC. Por lo general, estas clases se usan cada vez que se escribe el código de colecciones nuevas.
Uso de clases basadas en plantillas para la seguridad de tipos
Para utilizar clases basadas en plantillas
Declare una variable del tipo de clase de colección. Por ejemplo:
CList<int, int> m_intList;
Llame a las funciones miembro del objeto de colección. Por ejemplo:
m_intList.AddTail(100); m_intList.RemoveAll();
Si es necesario, implemente las funciones auxiliares y SerializeElements. Para más información sobre cómo implementar estas funciones, consulte Implementación de funciones auxiliares.
En este ejemplo, se muestra la declaración de una lista de enteros. El primer parámetro del paso 1 es el tipo de datos almacenados como elementos de la lista. El segundo parámetro especifica cómo se pasan y devuelven los datos de las funciones miembro de la clase de colección, como Add
y GetAt
.
Implementación de funciones auxiliares
Las clases de colección basadas en plantillas CArray
, CList
y CMap
usan cinco funciones auxiliares globales que se pueden personalizar según sea necesario para una clase de colección derivada. Para más información sobre estas funciones auxiliares, consulte Asistentes de clase de colección en la Referencia de MFC. La implementación de la función de serialización es necesaria para la mayoría de los usos de las clases de colección basadas en plantillas.
Serialización de elementos
Las clases CArray
, CList
y CMap
llaman a SerializeElements
para almacenar elementos de colección en un archivo o para leerlos desde él.
La implementación predeterminada de la función auxiliar SerializeElements
realiza una escritura bit a bit de los objetos al archivo, o bien una lectura bit a bit del archivo a los objetos, en función de si los objetos se almacenan en el archivo o se recuperan de este. Invalide SerializeElements
si esta acción no es adecuada.
Si la colección almacena objetos derivados de CObject
y se utiliza la macro IMPLEMENT_SERIAL
en la implementación del elemento de clase de colección, puede aprovechar la funcionalidad de serialización integrada en CArchive
y 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);
}
}
Los operadores de inserción sobrecargados para CArchive
llaman a CObject::Serialize
(o una invalidación de dicha función) para cada objeto CPerson
.
Uso de clases de colección que no son plantillas
MFC también admite las clases de colección introducidas con la versión 1.0 de MFC. Estas clases no se basan en plantillas. Se pueden usar para contener datos de los tipos admitidos CObject*
, UINT
, DWORD
, y CString
. Puede usar estas colecciones predefinidas (como CObList
) para contener colecciones de cualquier objeto derivado de CObject
. MFC también proporciona otras colecciones predefinidas para contener tipos primitivos, como UINT
y punteros void (void*
). Sin embargo, en general, a menudo resulta útil definir sus propias colecciones con seguridad de tipos para contener objetos de una clase más específica y sus derivados. Tenga en cuenta que hacerlo con las clases de colección no basadas en plantillas implica más trabajo que usar las clases basadas en plantillas.
Hay dos maneras de crear colecciones con seguridad de tipos con las colecciones que no son plantillas:
Use las colecciones que no son plantillas, con la conversión de tipos si es necesario. Este es el enfoque más sencillo.
Derive y amplíe una colección con seguridad de tipos que no es plantilla.
Para usar las colecciones que no son plantillas con conversión de tipos
Use directamente una de las clases que no son plantillas, como
CWordArray
.Por ejemplo, puede crear
CWordArray
, agregarle cualquier valor de 32 bits y, luego, recuperarlo. No es necesario hacer nada más. Solo tiene que usar la funcionalidad predefinida.También puede usar una colección predefinida, como
CObList
, para contener los objetos derivados deCObject
. Se define una colecciónCObList
para contener punteros aCObject
. Al recuperar un objeto de la lista, es posible que tenga que convertir el resultado en el tipo adecuado, ya que las funcionesCObList
devuelven punteros aCObject
. Por ejemplo, si almacena objetosCPerson
en una colecciónCObList
, debe convertir un elemento recuperado a fin de que sea un puntero a un objetoCPerson
. En el ejemplo siguiente, se usa una colecciónCObList
para contener objetosCPerson
:CPerson* p1 = new CPerson(); CObList myList; myList.AddHead(p1); // No cast needed CPerson* p2 = (CPerson*)myList.GetHead();
Esta técnica de usar un tipo de colección predefinido y la conversión según sea necesario puede ser adecuada para muchas de las necesidades de la colección. Si necesita más funcionalidad o más seguridad de tipos, use una clase basada en plantillas o siga el procedimiento siguiente.
Para derivar y ampliar una colección con seguridad de tipos que no es plantilla
Derive su propia clase de colección de una de las clases que no son plantillas predefinidas.
Al derivar la clase, puede agregar funciones contenedoras con seguridad de tipos para proporcionar una interfaz con seguridad de tipos a las funciones existentes.
Por ejemplo, si deriva una lista de
CObList
para contener objetosCPerson
, puede agregar las funciones contenedorasAddHeadPerson
yGetHeadPerson
, tal como se muestra a continuación.class CPersonList : public CObList { public: void AddHeadPerson(CPerson* person) { AddHead(person); } const CPerson* GetHeadPerson() { return (CPerson*)GetHead(); } };
Estas funciones contenedoras proporcionan una forma con seguridad de tipos para agregar y recuperar objetos
CPerson
de la lista derivada. Puede ver que, para la funciónGetHeadPerson
, simplemente encapsula la conversión de tipos.También puede agregar una funcionalidad nueva si define funciones nuevas que amplían las capacidades de la colección en lugar de simplemente encapsular la funcionalidad existente en contenedores con seguridad de tipos. Por ejemplo, en el artículo Eliminación de todos los objetos de una colección CObject, se describe una función para eliminar todos los objetos contenidos en una lista. Esta función se puede agregar a la clase derivada como una función miembro.