包括不工作的警卫

时间:2012-10-19 20:08:13

标签: c++ include compiler-errors

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

我读过this但这与变量声明/定义有关。 This答案似乎更有意义,但我不清楚如何解决这个问题。

// 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() {

}

4 个答案:

答案 0 :(得分:10)

您收到链接器错误,而不是编译器错误。您已在randarr()文件中实现了函数util.h,这意味着编译器会在randarr()example.cpp中看到Main.cpp的副本。当链接器将这些链接在一起时,它会抱怨,因为你不允许对同一个函数有多个定义。

您有两种选择:

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

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

答案 1 :(得分:8)

包含警卫不是错误的原因;你违反了One Definition Rule。由于 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) {
  // ...
}

答案 2 :(得分:3)

您可以在头文件中定义函数。这意味着这些功能在example.cppMain.cpp中定义。

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

答案 3 :(得分:0)

您的标题应该只包含您的函数的原型。原型将您的函数描述为其他文件,但不实现它。唯一的例外是模板,因为每个模板专门化都是在编译时构建的。

如果在头文件中实现函数,则在链接器时,您会发现函数内容的多次,这就是您遇到错误的原因。

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