无法从另一个命名空间创建类的实例?
Posted
技术标签:
【中文标题】无法从另一个命名空间创建类的实例?【英文标题】:Cannot create an instance of a class from another namespace? 【发布时间】:2012-02-23 14:07:03 【问题描述】:好的,这真的很奇怪。我从来没有遇到过这样的事情。
我的部分程序(编译失败)包含三个命名空间,如下:
// 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()'
我以前从未遇到过这样的事情......这看起来真的很奇怪,我什至不知道任何词语/术语来描述这个问题。
我将非常感谢任何帮助。
谢谢,
【问题讨论】:
你如何尝试链接它?您似乎忘记链接到定义 B 的文件。 我以一种非常愚蠢的方式编译整个程序。我只是“g++ -Wall *”它。也许这是个问题? 应该可以。我记得内联构造函数有问题,也许你可以尝试删除 B::Tree() 和 Tree::~Tree() 前面的内联 是的!那确实解决了! *** 上的你们太有帮助了!非常感谢 【参考方案1】:namespaceC.cc: undefined reference to `B::Tree::Tree()' namespaceC.cc: undefined reference to `B::Tree::~Tree()'
这些不是编译器错误,它们是链接器错误。问题是您声明了构造函数和析构函数,但从未定义它们。所以编译器找到声明并接受它们,但是链接器找不到定义来链接引用。
请参阅 this answer,了解什么是声明、什么是定义以及它们的优点/需要。
【讨论】:
我确实在 namespaceB.cc 文件中定义了构造函数和析构函数。我将编辑我的问题以使其更清楚 @BeyondSora:那么您要么没有编译 namespacB.cc 文件,要么没有将生成的目标文件传递给链接器。因为错误消息明确指出链接器找不到这些定义。【参考方案2】:您对B::Tree::Tree()
和B::Tree::~Tree()
的定义是内联声明的。这意味着它们仅在该源文件中可用,在任何其他文件中均不可用。
无论是从定义中删除inline
,还是将内联定义移动到需要它们的所有源文件包含的头文件中,都应该修复链接错误。
【讨论】:
你先生是男人!!!非常感谢你。在这里,我认为内联会提高效率等。我为了这件事熬夜到今天早上 4 点。非常感谢你!【参考方案3】:您必须在内联或 namespaceB.cc 中的某处为 B::Tree
编写构造函数和析构函数。通过创建B
的实例,您需要存在构造函数和析构函数。
【讨论】:
是的,我在 namespaceB.cc 中使用了类似“inline Tree::Tree() ... ...”这样的东西【参考方案4】:指针编译得很好,因为所有指针都是相同的。只是不同对象类型所允许的语义不同。 它会一直编译 find 直到您尝试使用它。 但是要创建一个实际的对象,您需要实际的定义。
要使用来自另一个命名空间的定义,您可以使用范围,或者使用 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!?
【讨论】:
【参考方案5】:你声明了 Tree 构造函数和析构函数,但你没有告诉我们你在哪里定义它们(你只是说你在 namespaceB.cc 中实现了 Tree)
假设您已经定义了它们,您必须确保在链接行中同时包含 namespaceC.o 和 namespaceB.o。
【讨论】:
【参考方案6】:这不是 命名空间 问题,也不是编译器错误。编译器很高兴,但链接器找不到B::Tree::Tree()
的定义。你需要提供源文件来实现,或者使用-c
标志来“编译”。
【讨论】:
【参考方案7】:首先,您自己声明了类Tree
的构造函数和析构函数,因此编译器没有提供默认实现——您需要自己实现它们! (或者只是删除那些声明...)。
仅包含标头是不够的,但您需要明确说明您正在使用来自这些标头的命名空间:
在namespaceC.cc
中,在包含namespace.B
之后添加using namespace B;
,或者更好的是,在类型前面加上命名空间限定符:
B::Tree *tree;
B::Tree tree;
【讨论】:
对不起,我的实际程序中确实有命名空间...我现在将编辑我的问题以更正它。【参考方案8】:我尝试了 Visual Studio 2005 中的代码。如果我删除 namespaceB.cc 中构造函数和析构函数的“内联”,它可以无错误地链接。
然后我发现了这个帖子:G++ won't accept inline constructors in C++
它说对于内联函数,您必须在每个调用该函数的文件中都有它的定义。所以建议将内联定义放在头文件中。
【讨论】:
以上是关于无法从另一个命名空间创建类的实例?的主要内容,如果未能解决你的问题,请参考以下文章