2 votes

Lorsque la superclasse détient un pointeur sur X, et la sous-classe sur Y : X

Je n'arrive pas à trouver un meilleur titre... merci d'éditer si vous le pouvez !

class AbstractGUIBase
{
...
};
class GUIConcrete : public AbstractGUIBase
{
...
};

class AbstractApplicationBase
{
 AbstractGUIBase *mGUI;
};

class MyApplication : public AbstractApplicationBase
{
 GUIConcrete *mGUI;
};

C'est essentiellement la configuration que j'ai... une classe de base d'application fournit une fonctionnalité commune, y compris une référence à une instance de classe de base de GUI mGUI . mGUI n'est jamais instancié que dans MyApplication ou d'autres sous-classes concrètes.

Je ne veux pas redéclarer mGUI dans les deux classes parce que je finis par faire quelque chose comme super::mGUI = mGUI = new ConcreteGUI() . Mais je ne veux pas non plus avoir à faire des castings. mGUI à chaque fois qu'il est utilisé dans MyApplication .

Y a-t-il un rythme normal ici ? Je pensais que vous pourriez faire un modèle AbstractApplicationBase sur le type de classe GUI mais je n'aime pas particulièrement la programmation par modèles.

J'utilise MSVC++2008, ce qui signifie que je ne dispose pas des outils modernes les plus sophistiqués.

3voto

Andy Prowl Points 62121

Je vais essayer d'éliminer les détails de votre modèle pour me concentrer sur la conception abstraite suivante :

                struct A                    struct DA : A 
                {                           {
                };                          };

//==============================================================================

                struct B                    struct DB : B 
                {                           { 
                    A* p;                       DA* pD; // Avoid this
                };                          };

Maintenant, ce que vous essayez de faire est d'éviter d'ajouter une extra à la variable membre DB et être capable de traiter le pointeur p hérité de B comme si elle était de type DA* .

Vous pouvez structurer les classes B y DB de cette façon :

struct B
{
private:
    A* p;
public:
    B(A* _p) : p(_p) { }
    A* get_p() { return p; }
}

struct DB : B
{
public:
    B(DA* _p) : B(_p) { }
    DA* get_p() { return static_cast<DA*>(A::get_p()); }
}

Superclasse B contiendra un pointeur de type A* . Ce pointeur est défini au moment de la construction. Si le constructeur est invoqué lors de la création d'une instance de DB un pointeur vers un objet de type DA sera stocké. DB fournit une fonction get_p() qui cache B de la version de get_p() et renvoie un pointeur (correctement casté) de type DA* .

En raison de cette conception, le static_cast<> sur DB::get_p() est garanti (à moins que vous n'utilisiez l'héritage virtuel, auquel cas vous devriez utiliser l'option moins efficace dynamic_cast<> ).

Opérations internes de B accéderait au pointeur p directement. Les clients de B le récupère par le biais d'un appel à B::get_p() . A l'intérieur de DB et pour les clients de DB également, vous accéderez à l'objet pointé par p en récupérant le pointeur par la fonction B::get_p() plutôt que de déréférencer directement p .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X