无法从另一个命名空间创建类的实例?
好吧,这真的很奇怪。我从来没有遇到过这样的事情。
我的程序的一部分(编译失败)包含三个命名空间,如下所示:
// 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()'
我以前从未遇到过这样的事情......这看起来真的很奇怪,我不知道甚至知道任何单词/术语来描述这个问题。
我将非常感谢任何帮助。
谢谢,
Okay, so this is really werid. I've never encountered anything like this.
Part of my program (Fails to compile) contains three namespaces as following:
// 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
Now, g++ went along just fine but the linker ld complains:
"namespaceC.cc: undefined reference to `B::Tree::Tree()'
"namespaceC.cc: undefined reference to `B::Tree::~Tree()'
I have never ever encountered anything like this before... This just seems really weird, I don't even know any words/terms to describe this problem.
I would much appreciate any help.
Thanks,
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这些不是编译器错误,它们是链接器错误。问题是您声明了构造函数和析构函数,但从未定义它们。因此,编译器找到声明并接受它们,但是链接器找不到定义来链接引用。
请参阅此答案了解什么是声明以及什么是声明定义以及它们的好处/需要什么。
Those are not compiler errors, they are linker errors. The problem is that you declared the constructor and destructor, but never defined them. So the compiler finds the declarations and accepts them, but the linker cannot find the definitions to link the references to.
See this answer for what is a declaration and what is a definition and what they are good/needed for.
B::Tree::Tree()
和B::Tree::~Tree()
的定义被声明为内联。这意味着它们仅在该源文件中可用,而不在任何其他文件中可用。从定义中删除
inline
,或者将内联定义移动到所有需要它们的源文件包含的头文件中,应该可以修复链接错误。Your definitions of
B::Tree::Tree()
andB::Tree::~Tree()
are declared inline. This means they are only available in that source file, not any others.Either removing
inline
from the definitions, or moving the inline definitions into a header file included by all source files that need them, should fix the link errors.您必须在内联或在 namespaceB.cc 中的某个位置编写
B::Tree
的构造函数和析构函数。通过创建B
的实例,您需要存在构造函数和析构函数。You have to write the constructor and destructor for
B::Tree
somewhere either inline or in namespaceB.cc. By creating an instance ofB
, you are requiring the existence of the constructor and destructor.该指针编译良好,因为所有指针都是相同的。只是不同对象类型允许的语义不同。
它会编译 find 直到您尝试使用它。
但要创建实际的对象,您需要实际的定义。
要使用其他命名空间中的定义,您可以使用范围,或者使用使用:
或:
The pointer compiles fine because all pointers are the same. It's just the semantics allowed for different object types differ.
It would have compiled find up until the point you tried to use it.
But to create an actual object, you need the actual definition.
To use definitions from another namespace, you either used scopes, or use using:
or:
您声明 Tree 构造函数 &析构函数,但您没有向我们展示定义它们的位置(您只是说您在namespaceB.cc中实现了Tree)
假设您已经定义了它们,则必须确保同时包含namespaceC.o和namespaceB .o 在你的链接线上。
You declare the Tree constructor & destructor, but you don't show us where you define them (you just say you implement Tree in namespaceB.cc)
Assuming you have defined them, you must ensure you are including both namespaceC.o and namespaceB.o on your link line.
这不是命名空间问题,也不是编译器错误。编译器很高兴,但链接器无法找到
B::Tree::Tree()
的定义。您需要提供用于实现的源文件,或使用-c
标志“仅编译”。That's not a namespace problem, neither a compiler error. The compiler is happy, but linker fails to find the definition of
B::Tree::Tree()
. You need to supply the source file for implementation, or use-c
flag to "just compile".首先,您自己声明了类
Tree
的构造函数和析构函数,因此编译器没有提供默认实现 - 您需要自己实现它们! (或者只是删除这些声明......)。包含标头还不够,但您需要明确说明您正在使用这些标头中的命名空间:
在
namespaceC.cc
中,在包含namespaceB;
之后添加using namespace B;
code>namespace.B 或者更好的是,在类型前面加上命名空间限定符:First, you declared constructor and destructor of class
Tree
yourself so compiler didn't provide default implementation - you need to implement them yourself! (Or just remove those declarations...).It is not enough to include headers but you need to explicitly say that you're using namespaces from those headers:
In
namespaceC.cc
addusing namespace B;
after you includenamespace.B
or, even better, prepend types with a namespace qualifier:我在 Visual studio 2005 中尝试了这些代码。如果我删除 namespaceB.cc 中构造函数和析构函数的“内联”,它可以毫无错误地链接。
然后我找到了这篇文章: G++ won't Accept inline constructors in C++
它表示对于内联函数,您必须在调用该函数的每个文件中都有其定义。所以建议将内联定义放在头文件中。
I tried the codes in Visual studio 2005. If I remove the "inline" in namespaceB.cc for the constructor and destructor, it can link without errors.
Then I found this post: G++ won't accept inline constructors in C++
it says that for inline functions you must have its definition in every file that calls the function. So it is recommended to put inline definition in header file.