2010-01-13 6 views
2

Je vois deux problèmes dans une configuration comme ceci:classe dérivée ne peut pas voir la classe parent correctement

namespace ns1 
    { 
    class ParentClass 
    { 
     protected: 
     void callback(); 
    }; 
    } 

    namespace ns1 
    { 
    namespace ns2 
    { 
     class ChildClass : public ParentClass 
     { 
     public: 
     void method() 
     { 
     registerCallback(&ParentClass::callback); 
     } 
     }; 
    } 
    } 
  1. ChildClass :: méthode() donne une erreur de compilation: "« NS1 :: ParentClass :: callback ': ne peut pas accéder au membre protégé déclaré dans la classe' ns1 :: ParentClass ' "
  2. ParentClass *pObj = new ChildClass() donne une erreur, qu'il ne peut pas effectuer la conversion sans cast. C++ peut couler heureusement, non?
+0

Pouvez-vous publier le contexte complet dans lequel '2.' donne une erreur? –

+0

ParentClass * pObj = new ChildClass() compile bien en utilisant votre exemple (en commentant l'appel registerCallback illégal) dans VC10B2. Vous devrez poster plus de détails sur votre erreur. –

+0

Pourquoi registerCallback est-il illégal? –

Répondre

6

Change:

registerCallback(&ParentClass::callback); 

... à:

registerCallback(&ChildClass::callback); 

La raison est parce que & ParentClass :: rappel est un typename pleinement qualifié, non résolu du contexte de ChildClass mais de contexte global. En d'autres termes, c'est le même problème que celui-ci:

class Thingy 
{ 
protected: 
    virtual int Foo() {}; 
}; 


int main() 
{ 
    Thingy t; 
    t.Foo(); 
    return 0; 

} 
+0

C'est intéressant; vous pouvez appeler ParentClass :: callback() depuis l'intérieur de method(), mais le fait de prendre un pointeur provoque une erreur. Pourquoi donc? – ceo

+0

Edité avec une explication, je l'espère utile. –

-1

Déclarez la fonction en tant que public.

Assurez-vous que la classe de base a destructor virtuelle ..

+1

Ceci est juste un hack bon marché. –

+1

Eh bien, pas le destructeur virtuel, c'est un point valide ... – daramarak

+0

@daramarak: Fair point. –

3

Une classe dérivée ne peut accéder aux membres protégés d'une classe de base si cette instance de classe de base est - et est accessible via - une instance de classe dérivée. Une classe dérivée n'a pas accès aux membres protégés d'autres types de classe de base. Lors de la formation d'un pointeur sur un membre, un membre protégé d'une classe de base peut être utilisé mais le nom utilisé pour définir le nom du membre doit être un nom de classe dérivé et non le nom de la classe de base. Impossible d'accéder 'l'erreur est correcte.

Pour le point 2., avec using ns1::ParentClass; et un using ns1::ns2::ChildClass; à la portée externe après la déclaration complète de ChildClass, je ne reçois aucune erreur avec votre déclaration.

+0

Il est accédé via une instance de classe dérivée. –

+0

Non, il n'y a pas d'instance lors de la création d'un pointeur sur membre avec '& scope :: member_name'. –

+0

Mais édité pour ajouter la raison _real_ que l'erreur générée est correcte. Vous êtes autorisé à accéder aux membres protégés de la classe de base lors de la formation d'un pointeur sur le membre, même si aucune instance n'est impliquée dans cette opération. –

Questions connexes