C++以前的定义错误

Nic*_*uiz 5 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);
}
Run Code Online (Sandbox Code Playgroud)

Alo*_*ave 13

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

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

class doc;
Run Code Online (Sandbox Code Playgroud)

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

在这种情况下,doc被引用的唯一方法是指向类的指针doc,因此前向声明也将起作用.

BottomLine:
包含头文件应该适合您如果您有适当的包含防护.它没有任何问题.
但是,由于上面给出的推理,前向声明类也应该对你有用.注意前向声明通常用于存在类的循环依赖性的情况.

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

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

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

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

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

  • 将它用作基类.
  • 用它来声明一个成员.
  • 使用此类型定义函数或方法.

鉴于可能性(由于不完整类型使用的上述限制),人们应该更喜欢包含标题的前向声明.


Ale*_*lex 5

你缺少的包括监护人。如果您只包含刚刚粘贴的文件,则需要确保在多次包含它们时,其他时候代码不会重复。所以你使用这样的构造。

 #ifndef _XXX_
 #define _XXX_
    /* your header here */
 #endif
Run Code Online (Sandbox Code Playgroud)