【问题标题】:Basic C++ Redefinition Error基本 C++ 重定义错误
【发布时间】:2016-02-24 21:20:19
【问题描述】:

我一直在阅读有关标头保护及其用于解决重新定义错误的信息,但我不太确定如何正确实施它。这是我正在尝试做的一个简化示例:

fileA.h

#include first_header.h
#include second_header.h

// code here

文件B.h

#include first_header.h
#include second_header.h

// code here

ma​​infile.cpp

#include fileA.h
#include fileB.h

// code here

现在问题出现在 mainfile.cpp 中,因为我需要同时包含 fileA.h 和 fileB.h 标头,但是它们中的每一个都包含相同的标头引用,因此给了我重新定义错误。在这种情况下,我不确定如何绕过它或正确实施标头保护。

【问题讨论】:

  • 如果未定义,您可以使用 #ifndef 等预处理器语句。
  • 如果first_header.hsecond_header.h 有包含保护,应该没有问题。在mainfile.cpp中,编译器会打开fileB.h,然后打开first_header.h,意识到定义了include头定义,忽略文件中的所有内容。
  • 请提供minimal reproducible example。你没有显示 first_header.h 和 second_header.h 也没有说明他们有(或没有)他们自己的警卫。

标签: c++


【解决方案1】:

首先,您需要在文件名周围加上引号或尖括号,如下所示: #include <fileA.h> 或者 #include "fileA.h"

从您发布的内容来看,您似乎并不真正了解标头守卫的工作原理。所以这里是纲要。

假设我有一个函数,我希望能够从不同的 c++ 文件中调用它。你首先需要一个头文件。 (你可以在你的 include 守卫里面做 include。)

#ifndef MYHEADER_HPP
#define MYHEADER_HPP

#include "first_header.h"
#include "second_header.h"

void MyFunction();

#endif

非包含预处理器行构成了所谓的“包含保护”,您应该始终保护您的头文件。

然后您在 .cpp 文件中实现所述功能,如下所示:

#include "MyHeader.hpp"

void MyFunction()
{
    // Implementation goes here
}

现在,你可以在其他代码中使用这个函数了:

#include "MyHeader.hpp"

int main()
{
    MyFunction();
}

如果您使用 IDE 编译和链接会为您处理,但以防万一,您可以使用 g++ 像这样编译和链接(假设“main.cpp”文件和“MyFunction.cpp”文件) :

g++ main.cpp -c
g++ MyFunction.cpp -c
g++ main.o MyFunction.o -o MyExecutable

我希望这会有所帮助,祝你好运!

【讨论】:

  • 谢谢。这是非常有用的。我对此还是很陌生。
  • @alduin 查看 cplusplus.com 上的这篇文章,它的内容非常丰富,而且我在开始编程时了解了 include 守卫:http://www.cplusplus.com/articles/Gw6AC542/ 祝你好运!
【解决方案2】:

逻辑: 检查是否定义了特定的宏,如果没有定义宏,定义它并包含头文件的内容。这将防止重复包含标题内容。

像这样:

文件 A:

#ifndef fileA_h
#define fileA_h

#include first_header.h
#include second_header.h

//code here

#endif

文件 B:

#ifndef fileB_h
#define fileB_h

#include first_header.h
#include second_header.h

//code here

#endif

【讨论】:

  • 这有助于我进一步了解头球后卫。谢谢。
【解决方案3】:

大多数编译器(例如 Visual Studio)也支持 #pragma once,可以使用它来代替表示为“#ifndef”的包含保护。您会在一些使用 MS Visual C++ 编写的遗留代码中发现这一点。

然而,

#ifndef MYHEADER_HPP
#define MYHEADER_HPP

// code here

#endif

更便携。

【讨论】:

  • 这个答案几乎没有问题。 1. 更多的是评论。 2. #pragma once 是一个包含守卫。 3. 我能想到几个不支持#pragma once 的著名编译器,而pragma 的问题是它们在不支持时经常被默默地忽略。在对编译指示进行大量投资之前,请确保您的编译器支持它。
  • 1.你是对的@user4581301。完全同意。 2. 只是想提一下,“#pragma once”也存在。因为还没有提到。如果他在其他人的代码中遇到它,更多的是告诉 OP 意味着什么,而不是提议使用它。 3. 一开始想把它作为评论提,但是Stackoverflow不允许我写评论,所以我把它放在了一个“答案”中。
  • 更像答案。我建议删除第一段的最后一行,因为它不是遗留的。 once 可能是未来的方式,只要解决一些错误和可移植性问题。
  • @user4581301 我没有说“它是遗留的”,我说它更常用于“遗留代码”(尤其是在 VS 代码中,可能是因为 MS 比例如 GCC 更早地支持它),就是这样一个区别。 “类似答案”是什么意思?你错过了什么?我认为问题的另一部分已在其他答案中得到解答,因此请考虑将“#pragma once”作为补充。
猜你喜欢
  • 1970-01-01
  • 2017-02-17
  • 1970-01-01
  • 2011-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多