c++先前定义错误

C++ previous definition error

本文关键字:错误 定义 c++      更新时间:2023-10-16

所以,感谢这个网站,我找到了我之前问题的答案。我正在向GNU automake项目中的类添加一个函数,该项目使用指向doc对象的指针。依赖项包含在Makefile中。将doc.hplsa.h按各自的顺序包含在文件中。然而,当我编译时,我会得到一个doc has not been declared错误。然后,我尝试在这里添加#include语句,这给出了一个previous redefinition of 'class doc'错误。

我知道我必须通过使用下面注释掉的class doc;行来声明doc;但是,我认为只有在声明一个按值传递对象的函数时才需要这样做。有人能给我解释一下为什么#include在这种情况下是不正确的吗?

#include "doc.h"
//class doc;
class plsa {
    // ...
    int infer(doc *trset, int maxiter, double noiseH);
}

为什么重定义错误?
请确保你的头文件有适当的头保护/包括保护。很可能您错过了添加头保护,因此由于多次包含头而导致多个类定义。

为什么前向声明在这种情况下是可以的?
当不包含头文件时,添加以下行:

class doc;

正向声明doc,这意味着对于编译器来说,它是一个不完整类型。对于不完全类型,我们不能创建它的对象,也不能做任何需要编译器知道doc的布局或doc只是一个类型的事实之外的事情。例如:编译器不知道它的成员是什么以及它的内存布局是什么。
但是,由于指向所有对象的指针需要相同的内存分配,因此,当仅将不完整类型引用为指针时,可以使用forward声明。

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

底线:
包括头文件应该为您工作,如果您有适当的包含保护到位。这并没有什么问题。
但是,由于上面给出的理由,向前声明类也应该适用。注意,前向声明通常用于类之间存在循环依赖的情况。

Include header FileForward Declaration哪个更好?
包含头文件只是将代码从头文件复制粘贴到包含该文件的任何地方,这基本上可以导致:

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

前向声明对于如何进一步使用不完整类型有自己的限制。
对于不完整类型,您可以:

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

对于不完整类型,不能:

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

考虑到可能性(由于上述对不完整类型使用的限制),我们应该选择前向声明而不是include Header。

您缺少包括监护人。如果您只是包含文件,它们只是粘贴,您需要确保当它们被多次包含时,它们在其他时候代码没有重复。所以你可以使用这样的结构:

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