C++以前的定义错误 [英] C++ previous definition error

查看:143
本文介绍了C++以前的定义错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 doc object. Dependencies were included in the Makefile.am file to include doc.h and plsa.h in the respective order. However, when I compiled, I would get a doc has not been declared error. Then, I tried adding the #include statement here, which gives a previous redefinition of 'class doc' error.

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

I learned that I have to declare doc by 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?

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

推荐答案

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

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.

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

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

class doc;

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

It Forward declares the class doc which 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 doc is 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.

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

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

底线:
如果您有适当的 Inclusion Guards,那么包含头文件应该对您有用.而且没有任何问题.
但是,由于上述原因,前向声明类也应该对您有用.请注意,前向声明通常用于类的循环依赖的情况.

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.

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

Which is better Include header File or 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:

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

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

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

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

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

With Incomplete type you cannot:

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

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

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

这篇关于C++以前的定义错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆