所以,多亏了这个网站,我找到了我之前问题的答案。我正在向GNU automake项目中的类添加一个函数,该函数使用指向doc
对象的指针。依赖关系包含在Makefile.am文件中,以便在相应的顺序中包含doc.h
和plsa.h
。但是,当我编译时,我会收到doc has not been declared
错误。然后,我尝试在此处添加#include语句,这会产生previous redefinition of 'class doc'
错误。
我了解到必须使用下面注释的doc
行声明class doc;
;但是,我认为只有在我声明一个按值传递对象的函数时才需要这样做。有人可以向我解释为什么#include在这种情况下不正确吗?
#include "doc.h"
//class doc;
class plsa {
// ...
int infer(doc *trset, int maxiter, double noiseH);
}
答案 0 :(得分:13)
为什么重新定义错误?
请确保您的标题文件具有相应的 Header Guards/Include Guards 。很可能您错过了添加标题保护,因此多次包含标题会导致多个类定义。
为什么在这种情况下前瞻声明是可以的?
而不是包括头文件,你添加行:
class doc;
转发声明类doc
,这意味着对于编译器来说,它是不完整类型。对于不完整的类型,无法创建它的对象或执行任何需要编译器知道doc
的布局或更多doc
只是一种类型的事实。
即:编译器不知道它的成员是什么以及它的内存布局是什么
但由于指向所有对象的指针只需要相同的内存分配,因此只需将不完整类型作为指针进行处理即可使用前向声明。
在这种情况下,引用doc
的唯一方法是指向类doc
的指针,因此前向声明也可以。
<强>底线:强>
包括头文件应该适合您如果您有适当的包含警卫就地。
它没有任何问题
但是,由于上面给出的推理,前向声明类也应该对你有用。注意前向声明通常用于存在类的循环依赖性的情况。
哪个更好Include header File
或Forward Declaration
?
包括头文件只是复制粘贴从标题到包含文件的位置的代码,这基本上可以导致:
前瞻声明对如何进一步使用不完整类型有其自身的局限性 对于不完整类型,您可以:
对于不完整类型,您不能:
考虑到可能性(由于上述不完全类型使用的限制),人们应该更喜欢前置声明而不是包含标题。
答案 1 :(得分:2)
你失踪包括监护人。如果你只是包含他们刚刚粘贴的文件,你需要确保它们被多次包含,而其他时候代码不重复。所以你使用这样的结构。
#ifndef _XXX_
#define _XXX_
/* your header here */
#endif