2008-12-18 8 views
2

Considérons l'exemple suivant. Il se compose de deux fichiers d'en-tête, déclarant deux espaces de noms différents:Espaces de noms C++: utilisation croisée

// a1.h 
#pragma once 
#include "a2.h" 

namespace a1 
{ 
    const int x = 10; 
    typedef a2::C B; 
} 

et le second est

// a2.h  
#pragma once 
#include "a1.h" 

namespace a2 { 
    class C { 
    public: 
    int say() { 
     return a1::x; 
    } 
    }; 
} 

Et un seul fichier source, main.cpp:

#include <iostream> 
#include "a1.h" 
#include "a2.h" 

int main() 
{ 
    a2::C c; 
    std::cout << c.say() << std::endl; 
} 

De cette façon, il doesn compilez pas (essayé GCC et MSVC). L'erreur est que les espaces de noms a1 ne sont pas déclarés (C2653 sous Windows). Si vous changez inclure ordre main.cpp cette façon:

#include "a2.h" 
#include "a1.h" 

vous obtenez un message d'erreur symétrique, à savoir a2 espace de noms est pas déclaré.

Quel est le problème?

+0

#pragma once est pas C++, il est une chose Microsoft. Meilleur remplacé par #ifdef A1_H #define A1_H ... #endif // A1_H – MSalters

Répondre

11

Vous devez utiliser une déclaration forward dans vos fichiers d'en-tête car vous disposez d'une référence circulaire. Quelque chose comme ceci:

// a1.h 
#pragma once 

namespace a2 { 
    class C; 
} 

namespace a1 
{ 
    const int x = 10; 
    typedef a2::C B; 
} 
3

Juste une supposition, mais votre référence d'inclusion est circulaire. Ce qui signifie que le compilateur ne peut pas déterminer quel en-tête doit être compilé en premier. a1 références a2 qui références a1.

Si possible, fusionnez/réorganisez les fichiers de sorte qu'il existe une chaîne d'inclusions non circulaire.

Espérons que ça aide!

+0

Vous pensez à mes pensées. Veuillez les renvoyer quand vous avez fini. – Marcin

1

Lorsque vous ajoutez a1.h d'abord, il tente immédiatement d'inclure a2.h avant de déclarer quoi que ce soit

références a2.h quelque chose dans l'espace de noms a1 qui n'a pas été déclarée encore

Lorsque vous incluez a2.h d'abord, il tente immédiatement d'inclure a1.h avant de déclarer quoi que ce soit

références a1.h quelque chose dans l'espace de noms a2 qui n'a pas été déclarée encore

Supprimer le typedef de a1.h, que vous n'utilisez pas, et ne pas inclure a2.h supprime le cycle.

Ou, comme par l'autre intervenant, avant de déclarer la classe C.

 
// a1.h 
#pragma once 
//#include "a2.h" 

namespace a1 
{ 
    const int x = 10; 
// typedef a2::C B; 
} 
Questions connexes