"Multiple definition of" 编写 header-only 模板库时出错
"Multiple definition of" error while writing a header-only template library
我的项目类似于此设置,当我需要在 main_class.h
中使用 my_template_library.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
在我编写的模板 header-only 库中,我首先在 class 中声明所有内容,然后定义 class 之外的所有内容,就像您通常在分隔 [= =79=] 到 .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
所以 header 文件是通过以下方式包含的:
- main.cpp -> main_class.h
- main_class.h
- main_class.cpp -> main_class.h
- my_template_library.h(就其本身?)
所以,我的问题是:
- 为什么包括守卫没有帮助?
- 如何防止这种情况发生?
Why include guards don't help?
在 相同 编译单元中包含防止冗余代码的守卫。
您收到有关不同 个编译单元声称拥有相同函数定义的链接器错误。
How to prevent this from happening?
你需要让那些非模板成员函数inline
避免违反One Definition Rule.
一种方法是将它们显式声明为内联。
inline MyTemplateLibrary::MyTemplateLibrary(){}
或者,class 定义中定义的函数是隐式内联的。
class MyTemplateLibrary
{
public:
MyTemplateLibrary() {}
void function()
{
std::cout << "function called!" << std::endl;
}
};
我的项目类似于此设置,当我需要在 main_class.h
中使用 my_template_library.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
在我编写的模板 header-only 库中,我首先在 class 中声明所有内容,然后定义 class 之外的所有内容,就像您通常在分隔 [= =79=] 到 .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
所以 header 文件是通过以下方式包含的:
- main.cpp -> main_class.h
- main_class.h
- main_class.cpp -> main_class.h
- my_template_library.h(就其本身?)
所以,我的问题是:
- 为什么包括守卫没有帮助?
- 如何防止这种情况发生?
Why include guards don't help?
在 相同 编译单元中包含防止冗余代码的守卫。
您收到有关不同 个编译单元声称拥有相同函数定义的链接器错误。
How to prevent this from happening?
你需要让那些非模板成员函数inline
避免违反One Definition Rule.
一种方法是将它们显式声明为内联。
inline MyTemplateLibrary::MyTemplateLibrary(){}
或者,class 定义中定义的函数是隐式内联的。
class MyTemplateLibrary
{
public:
MyTemplateLibrary() {}
void function()
{
std::cout << "function called!" << std::endl;
}
};