C++ 头文件中的多重定义

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2727582/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:31:09  来源:igfitidea点击:

multiple definition in header file

c++header-files

提问by Jér?me

Given this code sample:

鉴于此代码示例:

complex.h :

复杂的.h:

#ifndef COMPLEX_H
#define COMPLEX_H

#include <iostream>

class Complex
{
public:
   Complex(float Real, float Imaginary);

   float real() const { return m_Real; };

private:
   friend std::ostream& operator<<(std::ostream& o, const Complex& Cplx);

   float m_Real;
   float m_Imaginary;
};

std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
   return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}
#endif // COMPLEX_H

complex.cpp :

复杂.cpp:

#include "complex.h"

Complex::Complex(float Real, float Imaginary) {
   m_Real = Real;
   m_Imaginary = Imaginary;
}

main.cpp :

主.cpp :

#include "complex.h"
#include <iostream>

int main()
{
   Complex Foo(3.4, 4.5);
   std::cout << Foo << "\n";
   return 0;
}

When compiling this code, I get the following error:

编译此代码时,出现以下错误:

multiple definition of operator<<(std::ostream&, Complex const&)

I've found that making this function inlinesolves the problem, but I don't understand why. Why does the compiler complain about multiple definition? My header file is guarded (with #define COMPLEX_H).

我发现使用这个函数inline可以解决问题,但我不明白为什么。为什么编译器会抱怨多重定义?我的头文件受到保护(使用#define COMPLEX_H)。

And, if complaining about the operator<<function, why not complain about the public real()function, which is defined in the header as well?

而且,如果抱怨operator<<函数,为什么不抱怨public real()函数,它也在标题中定义?

And is there another solution besides using the inlinekeyword?

除了使用inline关键字之外还有其他解决方案吗?

回答by Michael Aaron Safyan

The problem is that the following piece of code is a definition, not a declaration:

问题在于以下代码是定义,而不是声明:

std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
   return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}

You can either mark the function above and make it "inline" so that multiple translation units may define it:

您可以标记上面的函数并使其“内联”,以便多个翻译单元可以定义它:

inline std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
   return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}

Or you can simply move the original definition of the function to the "complex.cpp" source file.

或者您可以简单地将函数的原始定义移动到“complex.cpp”源文件中。

The compiler does not complain about "real()" because it is implicitly inlined (any member function whose body is given in the class declaration is interpreted as if it had been declared "inline"). The preprocessor guards prevent your header from being included more than once from a single translation unit ("*.cpp" source file"). However, both translation units see the same header file. Basically, the compiler compiles "main.cpp" to "main.o" (including any definitions given in the headers included by "main.cpp"), and the compiler separately compiles "complex.cpp" to "complex.o" (including any definitions given in the headers included by "complex.cpp"). Then the linker merges "main.o" and "complex.o" into a single binary file; it is at this point that the linker finds two definitions for a function of the same name. It is also at this point that the linker attempts to resolve external references (e.g. "main.o" refers to "Complex::Complex" but does not have a definition for that function... the linker locates the definition from "complex.o", and resolves that reference).

编译器不会抱怨“real()”,因为它是隐式内联的(其主体在类声明中给出的任何成员函数都被解释为好像它已被声明为“内联”)。预处理器守卫防止您的头文件从单个翻译单元(“*.cpp”源文件”)中多次包含。但是,两个翻译单元看到相同的头文件。基本上,编译器将“main.cpp”编译为“main.o”(包括“main.cpp”包含的头文件中给出的任何定义),编译器分别将“complex.cpp”编译为“complex.o”(包括“complex”包含的头文件中给出的任何定义) .cpp”)。然后链接器将“main.o”和“complex.o”合并成一个二进制文件;正是在这一点上,链接器找到了同名函数的两个定义。也正是在这一点上,链接器尝试解析外部引用(例如,“main.o”指的是“Complex::Complex”,但没有该函数的定义……链接器从“complex. o”,并解析该引用)。

回答by XAder

Move implementation to complex.cpp

将实现移至 complex.cpp

Right now after including this file implementation is being compiled to every file. Later during linking there's a obvious conflict because of duplicate implementations.

在包含此文件实现之后,现在正在将其编译到每个文件中。稍后在链接过程中,由于重复实现,存在明显的冲突。

::real() is not reported because it's inline implicitly (implementation inside class definition)

::real() 未报告,因为它是隐式内联的(在类定义中实现)

回答by Paul Wintz

I was having this problem, even after my source and header file were correct.

我遇到了这个问题,即使我的源文件和头文件是正确的。

It turned out Eclipse was using stale artifacts from a previous (failed) build.

事实证明,Eclipse 正在使用来自先前(失败)构建的陈旧工件。

To fix, use Project > Cleanthen rebuild.

要修复,请使用Project > Clean然后重建。

回答by thayne

An alternative to designating a function definitionin a header file as inlineis to define it as static. This will also avoid the multiple definition error.

在头文件中指定函数定义的另一种方法inline是将其定义为static. 这也将避免多重定义错误。