C++ 以前的定义错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7919600/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:42:34  来源:igfitidea点击:

C++ previous definition error

c++classinclude

提问by Nick Ruiz

So, thanks to this website, I found the answer to my previous problem. I'm adding a function to a class in a GNU automake project that uses a pointer to a docobject. Dependencies were included in the Makefile.am file to include doc.hand plsa.hin the respective order. However, when I compiled, I would get a doc has not been declarederror. Then, I tried adding the #include statement here, which gives a previous redefinition of 'class doc'error.

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

I learned that I have to declare docby using the class doc;line commented out below; however, I thought that this was only necessary if I was declaring a function that passes the object by value. Can someone explain to me why the #include is incorrect in this case?

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

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

回答by Alok Save

Why the Redefinition errors?
Please ensure that your header files have appropriate Header Guards/Include Guards.It is most likely that you have missed adding header guards and hence that causes multiple class definitions due to the header getting included multiple times.

为什么会出现重新定义错误?
请确保您的头文件具有适当的Header Guards/Include Guards 。很可能您没有添加头文件保护,因此由于头文件被多次包含而导致多个类定义。

Why Forward Declaration is okay in this case?
When instead of including the header file you add the line:

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

class doc;

It Forward declaresthe class docwhich means for compiler it is an Incomplete type. With Incomplete types, One cannot create objects of it or do anything which needs the compiler to know the layout of docor more than the fact that docis just an type. i.e: The compiler does not know what are its members and what its memory layout is.
But Since pointers to all objects need just the same memory allocation, You can use the forward declaration when just reffering to an Incomplete type as a pointer.

Forward 声明了类doc,这意味着对于编译器它是一个Incomplete 类型。对于不完整的类型,人们不能创建它的对象或做任何需要编译器知道布局的事情,doc或者doc不仅仅是类型这一事实。即:编译器不知道它的成员是什么以及它的内存布局是什么。
但是由于指向所有对象的指针只需要相同的内存分配,因此您可以在将 Incomplete 类型作为指针引用时使用前向声明。

In this case the only way in which docis being referenced is an pointer to the class docand hence the Forward declaration will work as well.

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

BottomLine:
Including the header file should work for you If you have proper Inclusion Guards in-place. And there is nothing wrong with it.
However, Forward declaring the class should also work for you because of the reasoning given above.Note that forward declarations are usually used in case where there is a Circular Dependency of classes.

底线:
如果您有适当的包含保护,则包含头文件应该对您有用。它没有任何问题。
但是,由于上面给出的推理,前向声明类也应该对您有用。请注意,前向声明通常用于存在类的循环依赖关系的情况。

Which is better Include header Fileor Forward Declaration?
Including the header file just copy pastes the code from the header to wherever the file was included, which basically could lead to:

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

  • Increase in compilation time
  • Pollution of global namespace.
  • Potential clash of preprocessor names.
  • Increase in Binary size(in some cases though not always)
  • 编译时间增加
  • 全局命名空间的污染。
  • 预处理器名称的潜在冲突。
  • 二进制大小的增加(在某些情况下,但并非总是如此)

Forward Declaration has its own limitations on how the Incomplete type can be used further on.
With Incomplete type you can:

前向声明对于如何进一步使用 Incomplete 类型有其自身的限制。
使用 Incomplete 类型,您可以:

  • Declare a member to be a pointer or a reference to the incomplete type.
  • Declare functions or methods which accepts/return incomplete types.
  • Define functions or methods which accepts/return pointers/references to the incomplete type (but without using its members).
  • 将成员声明为指向不完整类型的指针或引用。
  • 声明接受/返回不完整类型的函数或方法。
  • 定义接受/返回指向不完整类型的指针/引用的函数或方法(但不使用其成员)。

With Incomplete type you cannot:

使用 Incomplete 类型,您不能:

  • Use it as a base class.
  • Use it to declare a member.
  • Define functions or methods using this type.
  • 将其用作基类。
  • 用它来声明一个成员。
  • 使用此类型定义函数或方法。

Given the possibility(due to above limitations on Incomplete type usage) One should prefer Forward Declaration over Including Header.

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

回答by Alex

You are missing include guardians. if you just include files they are just pasted you need to make sure when they are included multiple times that they other times the code isn't duplicated. so you use a construct like this.

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

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