C++ 使用ifdef时有多个定义

C++ 使用ifdef时有多个定义,c++,definition,include-guards,C++,Definition,Include Guards,我在编译时遇到了一个问题:myFunction的多个定义 我将在这里大大简化这个问题。基本上,我有3个文件:main、header和myLibrary main.cpp 页眉.hpp header.cpp myLibrary.hpp 那么,为什么编译器说我有多个myFunction的定义呢 我发现了一条线索:当我获取header.cpp并删除包含header.hpp的行时,程序编译时毫无怨言。另一方面,如果我从myLibrary.hpp中删除myFunction,程序也会编译而不会出现问题您应该

我在编译时遇到了一个问题:myFunction的多个定义 我将在这里大大简化这个问题。基本上,我有3个文件:main、header和myLibrary

main.cpp 页眉.hpp header.cpp myLibrary.hpp 那么,为什么编译器说我有多个myFunction的定义呢

我发现了一条线索:当我获取header.cpp并删除包含header.hpp的行时,程序编译时毫无怨言。另一方面,如果我从myLibrary.hpp中删除myFunction,程序也会编译而不会出现问题

您应该在.cpp文件中定义函数,而不是在头文件中。您可以在头文件中声明它们。您所做的是在头文件中定义它,因此当它被包含到多个文件中时,该函数将被复制。跨文件复制符号将抛出错误,除非它们是静态的

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
您应该在.cpp文件中定义函数,而不是在头文件中。您可以在头文件中声明它们。您所做的是在头文件中定义它,因此当它被包含到多个文件中时,该函数将被复制。跨文件复制符号将抛出错误,除非它们是静态的

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

您正在头文件中定义函数体。因此,在本例中,包含该标题的每个翻译单元main.cpp和header.cpp都将以其自身的函数体副本结束。当您尝试将这些多个单元链接在一起时,会出现重复定义错误

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

myLibrary.hpp

#ifndef LIB_HPP
#define LIB_HPP

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

#endif

您正在头文件中定义函数体。因此,在本例中,包含该标题的每个翻译单元main.cpp和header.cpp都将以其自身的函数体副本结束。当您尝试将这些多个单元链接在一起时,会出现重复定义错误

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

myLibrary.hpp

#ifndef LIB_HPP
#define LIB_HPP

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

#endif

Include-guard只能防止同一个头在同一个翻译单元中被包含两次,实际上通常是一个.cpp文件。例如,它可以防止执行此操作时出现错误:

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

int main()
{
}
但是,更一般地说,这意味着您是否包含一个已经作为另一个头的依赖项包含的头并不重要

但是,如果有两个.cpp文件包含相同的头,并且该头包含myLibrary.hpp等函数的定义,则每个.cpp文件都有其自己的定义。由于头包含在两个单独的翻译单元/.cpp文件中,因此包含保护将不起作用


最简单的方法是在头文件中声明函数,这会告诉包含头文件的每个文件该函数存在于某个位置,然后在.cpp文件中定义它,使其仅定义一次。

包含保护仅防止同一头文件在同一翻译单元中包含两次,实际上,它通常是一个.cpp文件。例如,它可以防止执行此操作时出现错误:

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

int main()
{
}
但是,更一般地说,这意味着您是否包含一个已经作为另一个头的依赖项包含的头并不重要

但是,如果有两个.cpp文件包含相同的头,并且该头包含myLibrary.hpp等函数的定义,则每个.cpp文件都有其自己的定义。由于头包含在两个单独的翻译单元/.cpp文件中,因此包含保护将不起作用


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

这不就是重复我的答案吗?这不就是重复我的答案吗?
#include "myLibrary.hpp"

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

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

int main()
{
}