2010-06-23 18 views
0

J'ai une classe héritée d'une classe de base abstraite.Polymorphisme: Accès à la variable de classe héritée

class CStateBase 
{ 
    friend class CApplication; 
    friend class CGraphics; 
    virtual int Update() =0; 
}; 

class CStateTitle: private CStateBase 
{ 
    friend class CApplication; 
    friend class CGraphics; 
    CApplication *f_App; 

    int m_iR; 

    int Update(); 

    CStateTitle(CApplication *App); 
    ~CStateTitle(); 
}; 

Dans un procédé d'une autre classe, CStateTitle est allouée dynamiquement en un pointeur CStateBase. Cependant, si j'utilise ce pointeur pour essayer d'accéder à la variable int m_iR, le compilateur cherche la variable dans CStateBase et fait donc une erreur. Si je pouvais déclarer virtual int m_iR dans la classe de base, je penserais que cela fonctionnerait bien, mais pour une raison quelconque, il ne me laisse pas déclarer les membres de données virtuelles. Quelle est la méthode recommandée pour contourner ce problème? Merci pour toute aide.

+0

Vous avez très probablement besoin d'un destructeur virtuel dans votre classe de base, voir par ex. Sutters [Virtualité] (http://www.gotw.ca/publications/mill18.htm). –

+1

De quelle manière une variable membre non-virtuelle ordinaire ne résout-elle pas votre problème? –

Répondre

3

Le meilleur moyen est de faire abstraction de l'accès de m_iR dans une fonction virtuelle. Un autre choix consisterait à déplacer m_iR de CStateTitle vers CStateBase. Cela n'a de sens que si chaque classe a besoin d'un m_iR.

Un dernier recours serait de faire un casting dynamique:

CStateBase *csb = ...; 

CStateTitle *cst = dynamic_cast<CStateTitle *>(csb); 
if (cst) 
{ 
    // have a valid CStateTitle 
} 
else 
{ 
    // csb is not pointing at a CStateTitle, do whatever is appropriate 
} 
+2

Votre idée finale est parfaitement valide, mais devrait être évitée si possible.C'est un drapeau rouge qui dit que vous n'avez pas assez réfléchi à votre polymorphisme. –

+0

@MarkRandom - Je suis d'accord avec vous, c'est pourquoi j'ai mis cette option en dernier. J'ai changé mon libellé en «dernier recours» pour le souligner. –

5

Vous devez héritez publiquement de la classe de base:

class CStateTitle: public CStateBase 

autrement CStateTitlen'est pas unCStateBase du point de vue du compilateur, donc vous ne pouvez pas accéder polymorphically CStateTitle objets via un pointeur CStateBase.

Vous ne pouvez pas avoir de membres de données virtuelles, seulement des méthodes virtuelles en C++. Une solution de contournement pourrait donc être de déclarer des méthodes d'accès virtuel pour votre membre de données.

1

Puisque vous essayez d'accéder à un de membre de classe dérivée directement à partir d'un pointeur de classe de base, vous ne sont évidemment pas polymorphisme invoquez. Donc vous pouvez utiliser dynamic_cast pour accéder à ce membre.

Conseil non sollicité: N'accédez pas directement aux variables membres. Pensez à votre hiérarchie et à la façon dont l'opération que vous essayez d'accomplir peut être accédée en utilisant une sorte d'interface cohérente utilisant une méthode virtuelle.

0

Vous pouvez définir une fonction virtuelle dans la classe de base pour effectuer l'accès requis (getter et/ou setter), ou, vous devrez convertir votre pointeur de base en un dérivé * et continuer à partir de là.

1

Vous ne pouvez pas avoir de variables de membre virtuelles.

Vous pouvez changer quand vous lancez:

CStateTitle *a = new CStateTitle(); 
a->m_iR = 1; 
CStateBase *b = a; 

ou réenregistrables jeté en utilisant quelque temps plus tard RTTI

CStateBase *a = new CStateTitle(); 
CStateTitle *b = dynamic_cast<CStateTitle*>(a); 
if(NULL != b) 
    b->m_iR = 1; 

ou ajouter une méthode setter virtuelle sur la classe de base si tous CStateBase où va avoir quelques-uns int qui devait être défini.

Questions connexes