2012-02-23 64 views
0

好的,這真是太棒了。我從來沒有遇到過這樣的事情。我的程序的無法從其他名稱空間創建類的實例?

部分(編譯失敗)包含三個命名空間如下:

// namespaceA.h 
namespace A { 
enum Kind { jimmy, david }; 
} 
// end of namespaceA.h 

// namespaceB.h 
#include "namespaceA.h" 
namespace B { 
class Tree { 
    public: 
    Tree *prev; 
    Tree *next; 
    Tree *down; 
    A::Kind kind; 

    Tree(); 
    ~Tree(); 
}; 
} 
// end of namespaceB.h 
// Implementation details of the class are placed in namespaceB.cc 
// Constructor/Desctructor defined in the namespaceB.cc file! 
// Something like this, 
#include "namespaceB.h" 
namespace B { 
inline Tree::Tree() { ... } 
inline Tree::~Tree() { ... } 
} 

// namespaceC.cc 
#include "namespace.B" 
namespace C { 
void run() { 
    B::Tree *tree; // FINE 
    B::Tree tree;  // Fail to compile!? 
} 
} 
// end of namespaceC.cc 

現在,G ++就相處得很好,但連接器ld抱怨:

"namespaceC.cc: undefined reference to `B::Tree::Tree()' 
"namespaceC.cc: undefined reference to `B::Tree::~Tree()' 

我從來沒有過遇到類似這樣的事情......這似乎真的很奇怪,我甚至不知道任何單詞/術語來描述這個問題。

我非常感謝任何幫助。

感謝,

+0

你如何嘗試鏈接呢?你似乎忘記了鏈接到定義B的文件。 – Tim 2012-02-23 14:12:08

+0

我以一種愚蠢的方式編譯整個程序。我只是「g ++ -Wall *」而已。也許這是一個問題? – 2012-02-23 14:16:19

+0

這應該工作。我記得有內聯構造函數的問題,也許你可以嘗試刪除B :: Tree()和Tree ::〜Tree()之前的內聯() – Tim 2012-02-23 14:23:02

回答

2

你的B::Tree::Tree()B::Tree::~Tree()定義聯聲明。這意味着它們只能在該源文件中使用,而不能在其他文件中使用。

要麼從定義中刪除inline,要麼將內聯定義移動到所有需要它們的源文件包含的頭文件中,應該修復鏈接錯誤。

+0

你先生是男人!謝謝你太多了。在這裏,我認爲內聯會提高效率等。今天早上我爲這件事耽誤了凌晨4點。男人非常感謝你! – 2012-02-23 14:25:03

1

你必須寫爲B::Tree構造函數和析構函數的地方串接或者在namespaceB.cc。通過創建B的實例,您需要構造函數和析構函數的存在。

+0

是的,我就是這樣做的namespaceB.cc沿着線的東西「內聯樹::樹(){...} ...」 – 2012-02-23 14:10:05

2
namespaceC.cc: undefined reference to `B::Tree::Tree()' 
namespaceC.cc: undefined reference to `B::Tree::~Tree()' 

這些都是沒有編譯器錯誤,他們鏈接錯誤。問題是,你宣佈構造函數和析構函數,但從來沒有定義他們。因此,編譯器找到聲明並接受它們,但是鏈接程序找不到定義以將引用鏈接到。

this answer什麼是一個聲明,什麼是一個定義,他們是好什麼/需要。

+0

我做了定義namespaceB.cc文件的構造器和析構函數。我將修改我的問題更清楚它 – 2012-02-23 14:11:47

+0

@BeyondSora:那你要麼沒有編譯namespacB.cc文件或者你不生成的對象文件傳遞給鏈接器。因爲錯誤信息明確表示鏈接程序無法找到這些定義。 – sbi 2012-02-23 14:13:29

0

指針編譯正常,因爲所有的指針都是一樣的。這只是不同對象類型所允許的語義不同。
它會編譯查找,直到您嘗試使用它。
但是要創建一個實際的對象,您需要實際的定義。

要使用的定義從另一個命名空間,你要麼使用範圍,或者使用using

#include "namespace.B" 
using namespace B; 
namespace C { 
void run() { 
    Tree *tree; // FINE 
    Tree tree;  // Fail to compile!? 
} 
} 

或:

#include "namespace.B" 
    namespace C { 
    void run() { 
     B::Tree *tree; // FINE 
     B::Tree tree;  // Fail to compile!? 
    } 
    } 
0

您聲明樹構造&析構函數,但你不t告訴我們你在哪裏定義它們(你只是說你在namespaceB.cc中實現Tree)

假設你已經定義了它們,你必須確保你包含了namespaceC。在你的鏈接行上有 namespaceB.o。

0

這不是一個命名空間問題,既不是一個編譯器錯誤。編譯器很高興,但鏈接器無法找到B::Tree::Tree()的定義。您需要提供實施的源文件,或者使用-c標誌來「編譯」。

0

首先你宣佈Tree類的構造函數和析構函數自己那麼編譯器沒有提供默認的實現 - 你需要自己實現這些功能! (或者只是刪除這些聲明...)。

這是不夠的,包括頭,但你需要明確地說,你正在使用的命名空間從這些標題:

namespaceC.cc添加using namespace B;你包括namespace.B後,或者甚至更好,前置類型與命名空間限定符:

B::Tree *tree;  
B::Tree tree;  
+0

我是sry,我在我的實際程序中有名稱空間...我現在編輯我的questio來糾正它。 – 2012-02-23 14:19:52

0

我試圖在Visual Studio 2005中的代碼如果我刪除了「內聯」在namespaceB.cc的構造函數和析構函數,它可以在不連接的錯誤。

然後我發現這個職位:G++ won't accept inline constructors in C++

它說,內聯函數,你必須有它的定義在每個調用該函數的文件。所以建議將內聯定義放在頭文件中。

+0

是的,似乎是這樣。我現在從我的代碼中刪除了所有內聯... – 2012-02-23 14:46:04

相關問題