目的
主要是解决在某个类中通过使用模板函数, 由于实例化, 导致在编译过程中会报错出现 “LNK 2019: unresolved external synbol …”.
unresolved external synbol.… 这类问题就是在连接过程中没有找到, 导致无法连接link…
我们知道一个编译单元(translation unit)是指一个.cpp文件以及它所#include的所有.h文件,.h文件里的代码将会被扩展到包含它的.cpp文件里,然后编译器编译该.cpp文件为一个.obj文件。不同的cpp文件是分开编译的。再由连接器(linker)进行连接成为一个.exe(二进制)文件。
在函数模板所包含的cpp文件中,如果没有对此模板进行实例化的过程,所编译的obj文件没有对类模板进行实例化,主函数的cpp文件也不会对此类模板进行实例化。也就不会生成二进制文件。
也就是说
template <typename T>
T addTest(T a, T b){
return a + b;
}
在编译过程只有在同一个cpp文件及其include的文件中有引用函数模板的过程,函数模板才会转化成对应的函数。
比如
int d = addTest<int>(3, 4);
qInfo() << "template: " << d;
这个时候编译的过程中就会生成int addTest(int ,int)这个函数,如果没有函数模板调用的过程,就不会生成任何函数。
解决方法
将类的声明和定义放在同一个.h文件中。
代码
template <typename T>
T addTest(T a, T b){
return a + b;
}
int main(int argc, char *argv[]){
int d = addTest<int>(3, 4);
qInfo() << "template: " << d;
}
这个是OK的。
.h
#ifndef TEMPLATETESTOBJECT_H
#define TEMPLATETESTOBJECT_H
#include <QObject>
class TemplateTestObject : public QObject
{
Q_OBJECT
public:
explicit TemplateTestObject(QObject *parent = nullptr);
template<typename T>
T add(T a, T b);
signals:
};
.cpp
#include "templatetestobject.h"
TemplateTestObject::TemplateTestObject(QObject *parent)
: QObject{parent}
{
}
template<typename T>
T TemplateTestObject::add(T a, T b)
{
return (a + b);
}
main.cpp
int main(int argc, char *argv[])
{
TemplateTestObject test;
int d1 = test.add<int>(3, 4);
qInfo() << "template: " << d1;
}
.cpp
#endif // TEMPLATETESTOBJECT_H
此时编译是会报错的。
.h
#ifndef TEMPLATETESTOBJECT_H
#define TEMPLATETESTOBJECT_H
#include <QObject>
class TemplateTestObject : public QObject
{
Q_OBJECT
public:
explicit TemplateTestObject(QObject *parent = nullptr);
template<typename T>
T add(T a, T b){
return (a + b);
}
signals:
};
.cpp
#include "templatetestobject.h"
TemplateTestObject::TemplateTestObject(QObject *parent)
: QObject{parent}
{
}
main.cpp
int main(int argc, char *argv[])
{
TemplateTestObject test;
int d1 = test.add<int>(3, 4);
qInfo() << "template: " << d1;
}
.cpp
#endif // TEMPLATETESTOBJECT_H
此时编译会ok。