【问题标题】:header file include-loop and multiple definition头文件包含循环和多重定义
【发布时间】:2012-08-09 03:37:27
【问题描述】:

我有一个 util.h 包含一个函数,该函数将在 a.h 和 'b.h' 中使用,此外,a.hb.h 将相互包含,以便访问定义在彼此。

//util.h

#ifndef _UTIL_H_
#define _UTIL_H_

#include <iostream>

void foo()
{
    std::cout << "foo\n";
}

#endif

//a.h, it has a a.cpp
#ifndef _A_H_
#define _A_H_

#include "util.h"
#include "b.h"

//some classes' definition

#endif

//b.h, it has a b.cpp
#ifndef _B_H_
#define _B_H_

#include "util.h"
#include "a.h"

//some classes' definition

#endif

我的问题是,foo 出现 multiple definition 错误。怎么样?

我认为问题可能在于,a.h 包含util.hb.h,而b.h 又包含util.h,所以我得到了多个def 错误。但这似乎没有意义,因为在util.h我写了#ifndef/#defineguards。

谁能帮帮我,谢谢。

【问题讨论】:

  • 多个定义是链接时错误,不应该与您的头文件(有声明,而不是定义)有关。你是怎么编译的?
  • @GordonBailey,我只是按照通常的方式编译它,比如g++ main.cpp a.cpp b.cpp
  • 如果你想把函数体放在头部,应该是static void foo() { /* body */ }
  • 以下划线和双下划线开头的符号由实现保留。使用 UTIL_H_ 之类的东西作为标题保护。

标签: c++ include-guards multiple-definition-error


【解决方案1】:

您的问题是由定义引起的,而不是简单地声明fooutils.h

对于这个例子,假设我们有:

a.cpp

#include "a.h"

b.cpp

#include "b.h"

ma​​in.cpp

#include "a.h"
#include "b.h"
#include "utils.h"


int main(){
    foo();
    return 0;
}

在预处理之后但在编译之前,您的文件现在看起来像这样(这是一种简化,但您明白了):

a.cpp

void foo()
{
    std::cout << "foo\n";
}

b.cpp

void foo()
{
    std::cout << "foo\n";
}

ma​​in.cpp

void foo()
{
    std::cout << "foo\n";
}

int main(){
    foo();
    return 0;
}

现在,当您编译时,您有 3 个 foo 的定义(它们都是相同的,但这无关紧要)。编译后,链接器无法知道为任何给定的foo 调用选择哪个定义,因此会产生错误。

不要在标题中定义foo,而是在utils.cpp中定义它,并且只在utils.h中声明,例如

utils.h

#ifndef _UTIL_H_
#define _UTIL_H_

void foo();

#endif

或者,或者,将foo 声明为staticinline

utils.h

#ifndef _UTIL_H_
#define _UTIL_H_

static void foo()
{
    std::cout << "foo\n";
}

/* OR */

inline void foo()
{
    std::cout << "foo\n";
}


#endif

只有当你想inline你的函数时,你才需要这样做。在这种情况下,编译器需要在每个使用它的翻译单元中定义该函数,因为它本质上变成了一个编译时宏。

【讨论】:

  • 很好地解释了:+1 =) 只是我要说的一个微妙点...确实,通常你会在头文件中声明函数并在源文件中定义它,但有时当您可以在标头中定义函数时-即提供内联函数以提高速度时:inline void foo() { std::cout &lt;&lt; "foo\n"; }。然而,在这种情况下,这是一件完全没有意义的事情!
  • 那么,inline 编译器会将foo 视为static
猜你喜欢
  • 1970-01-01
  • 2012-02-19
  • 1970-01-01
  • 2010-11-25
  • 2018-11-25
  • 2014-01-28
  • 2018-09-21
  • 2018-10-27
  • 1970-01-01
相关资源
最近更新 更多