c++ - "Multiple definition of"编写仅 header 模板库时出错

标签 c++ header-only

当我需要在 main_class.h 中使用 my_template_library.h 时,我的项目类似于此设置。

main.cpp

#include "main_class.h"

int main()
{
    MainClass m;
    return m.exec();
}

ma​​in_class.h

#ifndef MAIN_CLASS_H
#define MAIN_CLASS_H

#include "my_template_library.h"

class MainClass {
public:
    MainClass();
    int exec();
};

#endif // MAIN_CLASS_H

ma​​in_class.cpp

#include <iostream>

#include "main_class.h"

MainClass::MainClass(){}

int MainClass::exec()
{
    std::cout << "exec!" << std::endl;
    return 0;
}

my_template_library.h

#ifndef MY_TEMPLATE_LIBRARY_H
#define MY_TEMPLATE_LIBRARY_H

#include <iostream>

//#pragma message ("I'm being included past the include guards!")

class MyTemplateLibrary
{
public:
    MyTemplateLibrary();

    void function();
};

MyTemplateLibrary::MyTemplateLibrary(){}

void MyTemplateLibrary::function()
{
    std::cout << "function called!" << std::endl;
}

#endif // MY_TEMPLATE_LIBRARY_H

在我编写的仅包含模板头文件的库中,我首先在类中声明所有内容,然后在类外定义所有内容,就像将类分成 .h.cpp 代码,但是在.h 末尾添加了.cpp 文件,里面包含了守卫。只要我的模板库只被包含一次,这就可以正常工作,但是当它开始被包含得更多时,我遇到了一些非常令人困惑的问题。

$ g++ -o test main.cpp main_class.h main_class.cpp my_template_library.h 
/tmp/ccuFlEDZ.o: In function `MyTemplateLibrary::MyTemplateLibrary()':
main_class.cpp:(.text+0x0): multiple definition of `MyTemplateLibrary::MyTemplateLibrary()'
/tmp/ccZikorv.o:main.cpp:(.text+0x0): first defined here
/tmp/ccuFlEDZ.o: In function `MyTemplateLibrary::MyTemplateLibrary()':
main_class.cpp:(.text+0x0): multiple definition of `MyTemplateLibrary::MyTemplateLibrary()'
/tmp/ccZikorv.o:main.cpp:(.text+0x0): first defined here
/tmp/ccuFlEDZ.o: In function `MyTemplateLibrary::function()':
main_class.cpp:(.text+0xa): multiple definition of `MyTemplateLibrary::function()'
/tmp/ccZikorv.o:main.cpp:(.text+0xa): first defined here
collect2: error: ld returned 1 exit status

我对发生的事情感到困惑。我已将 #pragma message 添加到 my_template_library.h 中,以便对此有所了解,您在此处看到代码中已将其注释掉。当我取消注释并运行我得到的代码时

$ g++ -o test main.cpp main_class.h main_class.cpp my_template_library.h 
In file included from main_class.h:4:0,
                 from main.cpp:1:
my_template_library.h:6:63: note: #pragma message: I'm being included past the include guards!
 #pragma message ("I'm being included past the include guards!")
                                                           ^
In file included from main_class.h:4:0:
my_template_library.h:6:63: note: #pragma message: I'm being included past the include guards!
 #pragma message ("I'm being included past the include guards!")
                                                           ^
In file included from main_class.h:4:0,
             from main_class.cpp:3:
my_template_library.h:6:63: note: #pragma message: I'm being included past the include guards!
 #pragma message ("I'm being included past the include guards!")
                                                           ^
my_template_library.h:6:63: note: #pragma message: I'm being included past the include guards!
 #pragma message ("I'm being included past the include guards!")
                                                           ^
/tmp/ccmawdhP.o: In function `MyTemplateLibrary::MyTemplateLibrary()':
main_class.cpp:(.text+0x0): multiple definition of `MyTemplateLibrary::MyTemplateLibrary()'
/tmp/cc4XSnui.o:main.cpp:(.text+0x0): first defined here
/tmp/ccmawdhP.o: In function `MyTemplateLibrary::MyTemplateLibrary()':
main_class.cpp:(.text+0x0): multiple definition of `MyTemplateLibrary::MyTemplateLibrary()'
/tmp/cc4XSnui.o:main.cpp:(.text+0x0): first defined here
/tmp/ccmawdhP.o: In function `MyTemplateLibrary::function()':
main_class.cpp:(.text+0xa): multiple definition of `MyTemplateLibrary::function()'
/tmp/cc4XSnui.o:main.cpp:(.text+0xa): first defined here
collect2: error: ld returned 1 exit status

所以头文件是通过:

  1. main.cpp -> main_class.h
  2. 主类.h
  3. main_class.cpp -> main_class.h
  4. my_template_library.h(就其本身?)

所以,我的问题是:

  1. 为什么包括 guard 没有帮助?
  2. 如何防止这种情况发生?

最佳答案

Why include guards don't help?

相同编译单元中包含保护程序以防止冗余代码。

您收到有关不同 编译单元声称拥有相同函数定义的链接器错误。

How to prevent this from happening?

您需要使那些非模板成员函数内联 以避免违反One Definition Rule .

一种方法是显式声明它们内联。

inline MyTemplateLibrary::MyTemplateLibrary(){}

或者,在类定义中定义的函数是隐式内联的。

class MyTemplateLibrary
{
public:
    MyTemplateLibrary() {}

    void function()
    {
        std::cout << "function called!" << std::endl;
    }
};

关于c++ - "Multiple definition of"编写仅 header 模板库时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29218714/

相关文章:

c++ - 我应该尽可能使用#ifndef Q_MOC_RUN 吗?

C++ 值省略和析构函数?

c++ - 仅头文件库的好处

c++ - 在仅 header 库中拆分大文件

c++ - 我可以自动调用继承 QObject 的仅 header 对象吗?

c++ - Boost 的 TCP basic_resolver_query 构造函数的参数

c++ - QByteArray 到 char*,用 libcurl 发送

c++ - 我什么时候应该在现代 C++ 中使用(非头文件)源文件?

c++ - 需要建议 : does it make sense to include fmt lib in header-only library?

c++ - 不匹配的删除不再是未定义的行为?