2008-12-18 76 views
2

考虑下面的例子。它由两个头文件,声明了两个不同的命名空间:C++命名空间:交叉使用

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

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

,第二个是

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

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

和单一来源文件,main.cpp

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

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

这样,它不编译(尝试GCC和MSVC)。错误是a1名称空间未声明(Windows上的C2653)。如果更改包括main.cpp顺序是这样的:

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

你得到一个对称的错误信息,即a2命名空间不宣。

有什么问题?

+0

的#pragma一次不是C++,它是微软的事情。最好换成#ifdef A1_H #define A1_H ... #endif // A1_H – MSalters 2008-12-19 12:05:02

回答

11

您需要在头文件中使用前向声明,因为您有循环引用。事情是这样的:

// a1.h 
#pragma once 

namespace a2 { 
    class C; 
} 

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

只是一个猜测,但你的包含参考是循环的。这意味着编译器无法确定首先编译哪个头。 a1引用参考a1的a2。

如果可能的话,合并/重新组织这些文件,以便包含非循环链。

希望有帮助!

+0

你在想我的想法。完成后请返回。 – Marcin 2008-12-18 19:23:27

1

如果包括a1.h第一,它会立即尝试宣告什么

a2.h引用东西在命名空间A1还没有被宣布尚未

之前包括a2.h

如果包括a2.h第一,它会立即尝试宣告什么

a1.h引用东西在命名空间A2还没有被宣布尚未

之前包括a1.h

从a1.h中删除typedef,而不包括a2.h会删除该循环。

或者由其他的评论者,向前声明类C.

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

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