Comment étendre les fonctionnalités d'une classe de bibliothèque?

Problème

Je construis mon projet en Unicode mais j'ai besoin de la fonction CMyDoc :: Serialize() pour lire/écrire un fichier (think strings) en ASCII. Le problème est qu'une fois en Unicode, la classe CArchive lit/écrit automatiquement toutes les chaînes en Unicode que je ne veux pas.

Ma solution

Ma solution dérive ma propre classe CArchiveA de CArchive qui supporte aussi les chaînes ASCII. Voici ma définition de classe.

class CArchiveA : public CArchive
{

public:
    CArchiveA(CFile* pFile,
                UINT nMode,
                int nBufSize = 4096,
                void* lpBuf = NULL);

    CArchiveA( CArchive & ar );

    virtual ~CArchiveA();

    BOOL ReadStringA(CStringA& rString);
    LPSTR ReadStringA(_Out_z_cap_(nMax+1) LPSTR lpsz, _In_ UINT nMax);

    void WriteStringA(LPCSTR lpsz);


};

Maintenant j'espérais faire quelque chose comme ça dans la fonction Serialize du fichier doc.

void CTestDoc::Serialize(CArchive& ar)
{
    CArchiveA & ar_a ( ar );

   //text is of type CStringA

    if (ar.IsStoring())
    {
       //TODO: add storing code here
        ar_a.WriteStringA( text );
    }
    else
    {
       //TODO: add loading code here

        ar_a.ReadStringA( text );
    }
}

But the first line above CArchiveA & ar_a ( ar ); is compiler error.

Question

Peut-être que je me sens juste rouillé aujourd'hui mais comment puis-je convertir CArchive à ma propre classe dérivée CArchiveA pour que je puisse travailler avec? Est-ce mieux si je ne dérive pas de CArchive et écrit à la place des fonctions auxiliaires qui accepteraient CArchive comme premier paramètre et écriraient les chaînes ASCII?

Je trouve que c'est une étude de cas intéressante de l'extension de la fonctionnalité d'une classe de base à partir d'une bibliothèque donnée. J'adorerais explorer cet aspect dans la solution tout en recherchant la conception orientée objet. J'ai ma part de pensées, mais je voudrais d'abord vous écouter. La question en ce sens serait de savoir quelle est la meilleure façon de résoudre un problème comme celui-ci quand (disons) qu'une classe de bibliothèque manque un peu de fonctionnalité? Merci.

0

1 Réponses

Je pense que le confinement est un meilleur outil que l'héritage pour ce travail.

Par héritage public, vous dites que CArchiveA est un CArchive .

Cette relation n'est pas commutative. Cela s'apparente à une relation parent-enfant. Ainsi, un objet CArchive n'est pas un objet CArchiveA , et vous ne pouvez pas utiliser une référence CArchiveA pour pointer à un objet CArchive .

Un meilleur choix serait de faire de votre classe CArchiveA un wrapper autour de l'objet CArchive , et de le contenir plutôt que d'en hériter. Vous pouvez définir un constructeur pour CArchiveA qui accepte un objet ou une référence CArchive et conserve une référence, puis définit votre ReadString/WriteString méthodes pour faire ce que vous voulez.

Si CArchive implémente une interface abstraite, vous pouvez également en tirer CArchiveA . Mais sinon, vous ne voulez probablement pas utiliser l'héritage pour cela.

0
ajouté
C'est une bonne façon de le dire. Quand j'ai essayé `CTestDoc :: Serialize (CArchiveA & ar) 'la fonction ne serait plus appelée par le framework, donc ça parle de ce que dit CArchive n'est pas CArchiveA
ajouté l'auteur zar, source