使用#ifdef 时的多个定义

Multiple definitions when using #ifdef

编译时遇到问题:Multiple definitions of "myFunction()" 我将在这里大大简化问题。基本上,我有 3 个文件:"main"、"header" 和 "myLibrary"。

    #include "header.hpp"

    int main() {  }
    #ifndef HEADER_HPP
    #define HEADER_HPP

    #include "myLibrary.hpp"

    // ...

    #endif
    #include "header.hpp"

    // ...
    #ifndef LIB_HPP
    #define LIB_HPP

    #if defined(__unix__)
    #include <dlfcn.h>
    std::string myFunction() { return std::string(); }
    #endif

    #endif
    #include "myLibrary.hpp"

    //...

那么,为什么编译器说我有 Multiple definitions of "myFunction()"

我发现的一条线索:当我使用 header.cpp 并删除 #include "header.hpp" 的行时,程序编译时没有报错。另一方面,如果我改为擦除 myFunction(来自 myLibrary.hpp),程序也可以毫无抱怨地编译

您应该在 .cpp 文件中 定义 函数,而不是在头文件中。您在头文件中声明 它们。您正在做的是在头文件中定义它,因此当它被包含到多个文件中时,该函数就会重复。跨文件重复符号将引发错误,除非它们是 static.

myLibrary.cpp:

#include "myLibrary.hpp"
#ifdef(__unix__)
std::string myFunction() { return std::string(); }
#endif

myLibrary.hpp:

#ifndef LIB_HPP
#define LIB_HPP

#if defined(__unix__)
#include <dlfcn.h>
#include <string>
std::string myFunction();
#endif

#endif

您正在 header 文件中定义函数的 body。因此,您在其中包含 header 的每个翻译单元(在本例中为 main.cppheader.cpp)最终都会得到该函数 body 的副本。当您尝试 link 将这些多个单元放在一起时,您会收到 "duplicate definition" 错误。

函数需要在hpp文件中声明,在cpp文件中定义:

myLibrary.hpp

#ifndef LIB_HPP
#define LIB_HPP

#if defined(__unix__)
#include <dlfcn.h>
#include <string>
std::string myFunction();
#endif

#endif

myLibrary.cpp

#include "myLibrary.hpp"

#if defined(__unix__)
std::string myFunction()
{
    return std::string();
}
#endif

//...

Include guards 仅防止相同的 header 在同一个 翻译单元 中被包含两次,这实际上通常是一个 .cpp 文件。例如,这样做可以防止错误:

#include "header.h"
#include "header.h"

int main()
{
}

但是,更一般地说,这意味着您是否包含一个已经作为另一个 header 的依赖项包含的 header 并不重要。

但是,如果您有 两个 .cpp 文件包含相同的 header,并且 header 包含函数的定义(例如您的myLibrary.hpp) 那么每个 .cpp 文件都会有自己的定义(include guard 无济于事,因为 header 被包含在两个单独的翻译单元/.cpp 文件中)。

最简单的做法是在 header 中声明该函数,它告诉包含您的 header 的每个文件该函数存在于 某处 ,然后在.cpp文件中定义,这样只定义一次。