""的多重定义写入仅标题模板库时出错

时间:2015-03-23 19:26:49

标签: c++ header-only

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

的main.cpp

#include "main_class.h"

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

main_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

main_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时通常所做的那样代码,但在.cpp末尾添加了.h文件,内部包含警卫。只要我的模板库只包含一次,这种方法就可以正常工作,但是当它开始被包含在内时,我会遇到一些非常令人困惑的问题。

$ 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 - &gt; main_class.h
  2. main_class.h
  3. main_class.cpp - &gt; main_class.h
  4. my_template_library.h(单凭?)
  5. 所以,我的问题是:

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

1 个答案:

答案 0 :(得分:6)

  

为什么包括警卫不帮忙?

包含防护措施可防止相同编译单元内的冗余代码。

您收到关于不同编辑单元声称拥有相同功能定义的链接器错误。

  

如何防止这种情况发生?

您需要制作这些非模板成员函数inline,以避免违反One Definition Rule

一种方法是明确地将它们内联声明。

inline MyTemplateLibrary::MyTemplateLibrary(){}

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

class MyTemplateLibrary
{
public:
    MyTemplateLibrary() {}

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