包括不起作用的警卫

include guards not working

本文关键字:不起作用 包括      更新时间:2023-10-16

我已经定义了一个util.h文件,该文件具有我想在其他几个其他文件中使用的函数。该标头具有包含的罩,但是当我在两个不同的文件中使用它时,我会收到一个multiple definition of...错误。我在做什么错?

我已经阅读了这篇文章,但这与可变声明/定义有关。这个答案似乎更相关,但我不清楚如何解决此问题。

// util.h
// include lots of standard headers
#include ...
#ifndef UTIL_H
#define UTIL_H
using namespace std;
// multiple definition of `randarr(int, int, int)`
int* randarr(int size, int min, int max) {
    int *ret = new int[size];
    for (int i=0; i<size; i++)
            ret[i] = (int) (((double) rand() / RAND_MAX) * max) + min;
    return ret;
}
// no error
template<typename T> void printarr(T* v, int begin, int end) {
    for (int i=begin; i<end; i++)
    cout << v[i] << " ";
    cout << endl;
}
// multiple definition of `is_prime(int)`
bool is_prime(int n) {
    if (n == 2 || n == 3 || n == 5) return true;
    if (n <= 1 || (n&1) == 0) return false;
    for (int i = 3; i*i <= n; i += 2)
            if (n % i == 0) return false;
    return true;
}
#endif

// example.cpp
#include ...// lots of standard includes
#include "util.h"
void f() {
    randarr(...);
    printarr(...);
    is_prime(...);
    ...
}

// Main.cpp
#include "util.h"
int main() {
}

包括后卫不是造成错误的原因;您违反了一个定义规则。由于 util.h 都包含在2个源文件中,因此预处理后每个源文件后创建的翻译单元将包含每个函数的定义,从而导致多个定义错误。

要摆脱错误,请标记功能inline

inline int* randarr(int size, int min, int max) {
  // ...
}
template<typename T> 
inline void printarr(T* v, int begin, int end) {
  // ...
}
inline bool is_prime(int n) {
  // ...
}

您正在获得链接器错误,而不是编译器错误。您已经在util.h文件中实现了randarr()的函数,这意味着编译器在example.cppMain.cpp中的每个文件中都看到randarr()的副本。当链接器将它们链接在一起时,它会抱怨,因为您不允许使用相同功能的一个以上的定义。

您有两个选择:

  • randarr()声明为标题文件中的inline
  • randarr()的定义移至util.cpp文件

将相同的修复程序应用于is_prime()

您在标题文件中定义了功能。这意味着,这些功能的代码都包含在example.cppMain.cpp中。这也意味着代码将生成两次。这就是"多重定义"的原因。错误。

当您在单独的util.cpp中仅定义函数randarr()is_prime()时,错误将消失。

您的标题应仅包含功能的原型。一个原型将您的功能描述到其他文件,但不能实现它。唯一的例外是模板,因为每个模板专业化都是在编译时间上建立的。

如果您在标题文件中实现函数,在链接器时间,您会多次找到功能内容,这就是为什么您要面对错误。

randarris_prime的实现移动到另一个文件,然后将您util.h转换为:

#ifndef UTIL_H
#define UTIL_H
using namespace std;
int* randarr(int size, int min, int max);
template<typename T> void printarr(T* v, int begin, int end) {
    for (int i=begin; i<end; i++)
    cout << v[i] << " ";
    cout << endl;
}
bool is_prime(int n);
#endif