Serialização: criando uma classe serializável
Cinco principais etapas são necessárias para fazer uma classe serializável. São listados abaixo e explicados nas seguintes seções:
Com sua classe de CObject (ou qualquer classe derivada de CObject).
Substituindo a função de membro serializar.
Usando a macro de DECLARE_SERIAL na declaração da classe.
Definindo um construtor que não leve argumentos.
Usando a macro de IMPLEMENT_SERIAL no arquivo de implementação para a sua classe.
Se você chamar Serialize diretamente em vez de por >> meio dos operadores << de CArchive, as três últimas etapas não são necessárias para a serialização.
Com sua classe de CObject
O protocolo e a funcionalidade básicos de serialização são definidos na classe de CObject . Com sua classe de CObject (ou uma classe derivada de CObject), conforme mostrado na seguinte declaração de classe CPerson, você ganha acesso ao protocolo de serialização e a funcionalidade de CObject.
Substituindo a função de membro serializar
A função de membro de Serialize , que é definida na classe de CObject , é responsável para realmente serializar os dados necessários para capturar o estado atual de um objeto. A função de Serialize tem um argumento de CArchive que usa o para ler e gravar os dados do objeto. O objeto de CArchive tem uma função de membro, IsStoring, que indica se Serialize estiver armazenando (gravando dados) ou carregamento (dados de leitura). Usando os resultados de IsStoring como a guia, você insere os dados do objeto no objeto de CArchive com o operador insert (<<) ou os dados extract com o operador de extração**>>**().
Considere uma classe que é derivada de CObject e tem dois novos variáveis de membro, tipos de CString e WORD. O seguinte fragmento de declaração de classe mostra os novos variáveis de membro e a declaração da função de membro substituída de Serialize :
class CPerson : public CObject
{
public:
DECLARE_SERIAL( CPerson )
// empty constructor is necessary
CPerson();
virtual ~CPerson();
CString m_name;
WORD m_number;
void Serialize( CArchive& archive );
};
Para substituir a função de membro serializar
Chamar sua versão da classe base de Serialize para garantir que a parte herdada do objeto é serializada.
Inserir ou extrair as variáveis de membros específicos da sua classe.
Os operadores de inserção e de extração interagem com a classe de arquivo morto para ler e gravar os dados. O exemplo a seguir mostra como implementar Serialize para a classe de CPerson declarada anterior:
void CPerson::Serialize( CArchive& archive ) { // call base class function first // base class is CObject in this case CObject::Serialize( archive ); // now do the stuff for our specific class if( archive.IsStoring() ) archive << m_name << m_number; else archive >> m_name >> m_number; }
Você também pode usar as funções de membro de CArchive::Read e de CArchive::Write para ler e gravar grandes quantidades de dados sem-tipo.
Usando a macro de DECLARE_SERIAL
A macro de DECLARE_SERIAL é necessário na declaração das classes que ofereça suporte à serialização, como mostrado a seguir:
class CPerson : public CObject
{
public:
DECLARE_SERIAL( CPerson )
Definindo um construtor sem argumentos
O MFC requer um construtor padrão quando recriar seus objetos como desserializado (carregado do disco). O processo de desserialização preencherá todas as variáveis do membro com os valores necessários para recriar o objeto.
Este construtor pode ser declarado, protegido, público ou particular. Se você o fizer protegido ou particular, você ajuda a assegurar que será usado por funções de serialização. O construtor deve colocar o objeto em um estado que permite que foi excluído se necessário.
Dica
Se você esquecer definir um construtor sem argumentos em uma classe que usa macros de DECLARE_SERIAL e de IMPLEMENT_SERIAL , você não terá nenhum aviso “disponível do compilador do construtor padrão” na linha onde a macro de IMPLEMENT_SERIAL é usado.
Usando a macro de IMPLEMENT_SERIAL na implementação Arquivo
A macro de IMPLEMENT_SERIAL é usada para definir as várias funções necessárias quando você deve derivar uma classe de CObjectserializável. Você usa esta macro no arquivo de implementação .CPP () para a sua classe. Os primeiros dois argumentos para macro é o nome da classe e o nome da sua classe base imediata.
O terceiro argumento para esta macro é um número de esquema. O número de esquema é essencialmente um número de versão para objetos da classe. Use um inteiro maior que ou igual a 0 para o número de esquema. (Não confunda esse número de esquema com a terminologia de base de dados).
As verificações de código de serialização MFC o número do esquema ao ler objetos na memória. Se o número do esquema do objeto no disco não corresponde ao número de esquema da classe na memória, a biblioteca lançará CArchiveException, impedindo que o programa lê uma versão incorreta de um objeto.
Se desejar que sua função de membro de Serialize para poder ler várias versões - ou seja, arquivos gravados com versões diferentes do aplicativo — você pode usar o valor VERSIONABLE_SCHEMA como um argumento para macro de IMPLEMENT_SERIAL . Para obter informações de uso e um exemplo, consulte a função de membro de GetObjectSchema da classe CArchive.
O exemplo a seguir mostra como usar IMPLEMENT_SERIAL para uma classe, CPerson, que é derivada de CObject:
IMPLEMENT_SERIAL( CPerson, CObject, 1 )
Quando você tem uma classe serializável, é possível serializar objetos da classe, como descrito no artigo Serialização: Serializando um objeto.