2011-04-12 8 views
13

je l'exemple de code suivant ne compile pas:héritage privé: Nom erreur de recherche

#include <stdio.h> 

namespace my 
{ 
    class base1 
    { // line 6 
    }; 

    class base2: private base1 
    { 
    }; 

    class derived: private base2 
    { 
    public: 
     // The following function just wants to print a pointer, nothing else! 
     void print(base1* pointer) {printf("%p\n", pointer);} 
    }; 
} 

L'erreur qui imprime gcc est:

test.cpp:6: error: `class my::base1' is inaccessible

test.cpp:17: error: within this context

Maintenant, je peux deviner ce que le problème est: en regardant la déclaration de print, le compilateur voit base1 et pense: base1 est le sous-objet de classe de base de derived* this, mais vous n'avez pas accès! Alors que j'ai l'intention que base1 devrait être juste un nom de type. Comment puis-je voir dans la norme C++ que c'est un comportement correct, et pas un bogue dans le compilateur (je suis sûr que ce n'est pas un bug, tous les compilateurs que j'ai vérifiés se comportaient ainsi)?

Comment réparer cette erreur? Tous les correctifs suivants fonctionnent, mais lequel dois-je choisir?

void print(class base1* pointer) {}

void print(::my:: base1* pointer) {}

class base1; void print(base1* pointer) {}


Edit:

int main() 
{ 
    my::base1 object1; 
    my::derived object3; 
    object3.print(&object1); 
} 
+0

Pouvez-vous poster la main()? –

+0

Bon exemple montrant que l'héritage privé n'est pas du tout la même chose que la composition! – curiousguy

Répondre

12

La section que vous recherchez est 11.1. Il suggère d'utiliser :: :: mon Base1 * à travailler autour de ceci:

[ Note: In a derived class, the lookup of a base class name will find the injected-class-name instead of the name of the base class in the scope in which it was declared. The injected-class-name might be less accessible than the name of the base class in the scope in which it was declared. — end note ]

[ Example: 
class A { }; 
class B : private A { }; 
class C : public B { 
A *p; 
// error: injected-class-name A is inaccessible 
:: A * q ; 
// OK 
}; 
+0

pourriez-vous expliquer ce qu'est le nom de la classe injectée? – davka

+1

Chapitre 9, point 2: Un nom de classe est inséré dans la portée dans laquelle il est déclaré immédiatement après la visualisation du nom de la classe. Le nom de classe est également inséré dans la portée de la classe elle-même; C'est ce qu'on appelle le nom de la classe injectée. Pour les besoins de la vérification d'accès, le nom de la classe injectée est traité comme s'il s'agissait d'un nom de membre public. Un spécificateur de classe est communément appelé définition de classe. Une classe est considérée comme définie après que l'accolade de fermeture de son spécificateur de classe a été vue même si ses fonctions membres ne sont généralement pas encore définies. –

+1

Si vous êtes satisfait de la réponse fournie, @anatolyg, pourriez-vous marquer ceci comme accepté afin que les autres puissent le voir aussi? –