2012-02-23 68 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

相关问题