2008-12-18 79 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; 
}