C ++以前的定义错误

时间:2011-10-27 17:02:26

标签: c++ class include

所以,多亏了这个网站,我找到了我之前问题的答案。我正在向GNU automake项目中的类添加一个函数,该函数使用指向doc对象的指针。依赖关系包含在Makefile.am文件中,以便在相应的顺序中包含doc.hplsa.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);
}

2 个答案:

答案 0 :(得分:13)

为什么重新定义错误?
请确保您的标题文件具有相应的 Header Guards/Include Guards 。很可能您错过了添加标题保护,因此多次包含标题会导致多个类定义。

为什么在这种情况下前瞻声明是可以的?
而不是包括头文件,你添加行:

class doc;

转发声明doc,这意味着对于编译器来说,它是不完整类型。对于不完整的类型,无法创建它的对象或执行任何需要编译器知道doc的布局或更多doc只是一种类型的事实。 即:编译器不知道它的成员是什么以及它的内存布局是什么 但由于指向所有对象的指针只需要相同的内存分配,因此只需将不完整类型作为指针进行处理即可使用前向声明。

在这种情况下,引用doc的唯一方法是指向类doc的指针,因此前向声明也可以。

<强>底线:
包括头文件应该适合您如果您有适当的包含警卫就地。 它没有任何问题 但是,由于上面给出的推理,前向声明类也应该对你有用。注意前向声明通常用于存在类的循环依赖性的情况。

哪个更好Include header FileForward Declaration
包括头文件只是复制粘贴从标题到包含文件的位置的代码,这基本上可以导致:

  • 增加编译时间
  • 全球命名空间的污染。
  • 预处理程序名称的潜在冲突。
  • 增加二进制大小(在某些情况下,但并非总是如此)

前瞻声明对如何进一步使用不完整类型有其自身的局限性 对于不完整类型,您可以:

  • 将成员声明为指针或对不完整类型的引用。
  • 声明接受/返回不完整类型的函数或方法。
  • 定义接受/返回指向不完整类型的指针/引用的函数或方法(但不使用其成员)。

对于不完整类型,您不能:

  • 将其用作基类。
  • 用它来宣布成员。
  • 使用此类型定义函数或方法。

考虑到可能性(由于上述不完全类型使用的限制),人们应该更喜欢前置声明而不是包含标题。

答案 1 :(得分:2)

你失踪包括监护人。如果你只是包含他们刚刚粘贴的文件,你需要确保它们被多次包含,而其他时候代码不重复。所以你使用这样的结构。

 #ifndef _XXX_
 #define _XXX_
    /* your header here */
 #endif