2010-05-07 5 views
4

J'ai un problème avec Visual C++ 2005, où des classes internes apparemment avec le même nom, mais dans différentes classes externes sont confondues.Problème avec les classes internes du même nom dans Visual C++

Le problème se produit pour deux couches, chaque couche ayant une interface d'écoute en tant que classe interne. B est un écouteur de A, et a son propre écouteur dans une troisième couche au-dessus (non montré).

La structure du code ressemble à ceci:

Ah

class A 
{ 
public: 
    class Listener 
    { 
    public: 
     Listener(); 
     virtual ~Listener() = 0; 
    }; 
    // ... 
}; 

Bh

class B : public A::Listener 
{ 
    class Listener 
    { 
    public: 
     Listener(); 
     virtual ~Listener() = 0; 
    }; 
    // ... 
}; 

A :: Listener() et A :: ~ Listener() sont définis dans A.cpp.

B.cpp

B::Listener::Listener() {} 
B::Listener::~Listener() {} 

je reçois l'erreur

B.cpp(49) : error C2509: '{ctor}' : member function not declared in 'B' 

Le compilateur C++ pour Renesas SH2A n'a pas de problème avec cela, mais il est plus libéral que Visual C++ à d'autres égards , aussi.

Si je renomme les interfaces de l'écouteur pour avoir des noms différents, le problème disparaît, mais je voudrais éviter cela (les noms de classe réels au lieu de A ou B sont plutôt longs).

Est-ce que je fais le bon C++, ou la plainte par Visual C++ est-elle justifiée?

Existe-t-il un moyen de contourner ce problème sans renommer les interfaces d'écouteur?

+0

Qu'est-ce que '{ctor}'? Est-ce 'B :: Listener :: Listener()'? Êtes-vous sûr de ne pas avoir une faute de frappe dans l'en-tête ou dans le fichier d'implémentation, de sorte que la déclaration et la définition ne correspondent pas? En outre, je suppose que vous avez des points-virgules après les déclarations de classe, 'A :: ~ Listener()' est défini et 'A :: Listener' est public. Je peux vous dire que, étant donné que ceux-ci sont corrigés, le code compile sur g ++ 4.0.1 sous OS X 10.5.8. – wilhelmtell

+0

starblue, je l'ai réparé pour reproduire le problème - faites-le vous-même la prochaine fois. –

+0

Merci, j'ai aussi ajouté le 'public' manquant dans' B'. – starblue

Répondre

1

le code que vous avez publié a produit la même erreur de compilation que celle décrite sur ma machine. Je ne suis pas si sûr de ce qu'est exactement le problème, mais j'ai le sentiment qu'hériter d'une classe virtuelle pure et déclarer une classe virtuelle pure dans le descendant pourrait ne pas être une bonne idée.

j'ai réussi à compiler une version modifiée, peut-être que cela vous aide à résoudre vos problèmes:

class OuterA 
{ 
    public: 
    class Listener 
    { 
     public: 
     Listener() {} 
     virtual ~Listener() = 0 {} 
    }; 

    OuterA() {} 
    ~OuterA(){} 
}; 

class OuterB : public OuterA::Listener 
{ 
    public: 
    class Listener 
    { 
     public: 
     Listener() {} 
     ~Listener() {} 
    }; 

    OuterB() {} 
    ~OuterB() {} 
}; 

// EDIT pour éviter cteur en ligne et dtor

Si vous utilisez typedefs pour cacher les noms des Les auditeurs au moins mon code de démonstration compile et liens:

// tête

class OuterA 
{ 
    public: 
    class Listener 
    { 
     public: 
     Listener(); 
     virtual ~Listener() = 0; 
    }; 

    OuterA(); 
    ~OuterA(); 
}; 

class OuterB : public OuterA::Listener 
{ 
    public: 
    class Listener 
    { 
     public: 
     Listener(); 
     virtual ~Listener() = 0; 
    }; 

    OuterB(); 
    ~OuterB(); 
}; 

// implémentation

OuterA::OuterA(){} 
OuterA::~OuterA(){} 

OuterA::Listener::Listener(){} 
OuterA::Listener::~Listener(){} 

typedef OuterB::Listener BListener; 

OuterB::OuterB() {} 
OuterB::~OuterB(){} 

BListener::Listener(){} 
BListener::~Listener(){} 
+0

Malheureusement, sans déclarer les constructeurs et les destructeurs en ligne, cela conduit à des symboles en double lors de la liaison. Les déclarer en ligne n'est pas possible, car cela viole nos règles de codage (vérifié par QAC). – starblue

+0

depuis que j'aime énigmes comme ça, j'ai essayé un autre tour - en utilisant un typedef pour masquer le nom fonctionne –

+0

Nice, je vais essayer que la semaine prochaine. – starblue