提问人:Huy Le 提问时间:3/8/2022 最后编辑:Huy Le 更新时间:3/8/2022 访问量:127
遵循教程时出现 C++ 模板类标头-源分离链接错误
C++ template class header-source separation linking error when following tutorial
问:
----------------
// fishers.h
#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <map>
#include <math.h>
#include <cstring>
namespace tsfresh
{
template<typename T=double>
class FisherTest {
static_assert(std::is_floating_point_v<T>, "FisherTest template T must be float or double");
public:
FisherTest();
T pvalue(int a, int b, int c, int d);
private:
T pValueLog(int a, int b, int c, int d);
};
}
// fishers.cpp
#include "fishers.h"
namespace tsfresh
{
template<typename T>
FisherTest<T>::FisherTest() {
}
template<typename T>
T FisherTest<T>::pvalue(int a, int b, int c, int d) {
return pValueLog(a,b,c,d);
}
template<typename T>
T FisherTest<T>::pValueLog(int a, int b, int c, int d) {
return 0;
}
}
//---
// https://www.codeproject.com/Articles/48575/How-to-Define-a-Template-Class-in-a-h-File-and-Imp
void TempFunc()
{
tsfresh::FisherTest<float> FisherTestFloatObj;
tsfresh::FisherTest<double> FisherTestDoubleObj;
}
// main.cpp
#include <cassert>
#include <iostream>
#include <vector>
#include "fishers.h"
using namespace std;
bool floatEqual(double a, double b) {
return fabs(a-b) <= 1e-6;
}
int main()
{
auto fisher = tsfresh::FisherTest<double>();
int a[] = {1,2,3,4};
cout << fisher.pvalue(a[0], a[1], a[2], a[3]) << "\n";
cout << "All tests passed\n";
return 0;
}
我需要在cpp文件中隐藏实现细节,因此我需要将模板类的头文件和源文件分开。我制作了 2 个要在 .cpp 文件中使用的模板类实例(按照上面链接中的解决方案),但我仍然收到链接错误。
我使用的编译命令是:g++ -o test main.cpp fishers.cpp -std=c++17
我收到以下错误:tsfresh::FisherTest::p value(int, int, int, int)''main.cpp:(.text+0x93): undefined reference to
我需要更改什么才能使这项工作正常工作?我总是使用仅标头模板类,所以我不知道出了什么问题。
答:
1赞
user12002570
3/8/2022
#1
我需要更改什么才能使这项工作正常工作?
你需要把类模板的成员函数的实现放在头文件中,如下图所示:FisherTest
fishers.h
渔民.h
#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <map>
#include <math.h>
#include <cstring>
namespace tsfresh
{
template<typename T=double>
class FisherTest {
static_assert(std::is_floating_point_v<T>, "FisherTest template T must be float or double");
public:
FisherTest();
T pvalue(int a, int b, int c, int d);
private:
T pValueLog(int a, int b, int c, int d);
};
//implementation
template<typename T>
FisherTest<T>::FisherTest() {
}
template<typename T>
T FisherTest<T>::pvalue(int a, int b, int c, int d) {
return pValueLog(a,b,c,d);
}
template<typename T>
T FisherTest<T>::pValueLog(int a, int b, int c, int d) {
return 0;
}
}
//declaration for tempfunc
void TempFunc();
渔民.cpp
#include "fishers.h"
void TempFunc()
{
tsfresh::FisherTest<float> FisherTestFloatObj;
tsfresh::FisherTest<double> FisherTestDoubleObj;
}
main.cpp
#include <cassert>
#include <iostream>
#include <vector>
#include "fishers.h"
#include <type_traits>
using namespace std;
bool floatEqual(double a, double b) {
return fabs(a-b) <= 1e-6;
}
int main()
{
auto fisher = tsfresh::FisherTest<double>();
int a[] = {1,2,3,4};
cout << fisher.pvalue(a[0], a[1], a[2], a[3]) << "\n";
cout << "All tests passed\n";
return 0;
}
演示。
我所做的一些修改包括:
- 将类模板的成员函数的实现移到了 header 中。
FisherTest
fishers.h
- 添加了内部头文件的声明。
TempFunc
fishers.h
- 对应的定义是源文件旁边。
TempFunc
fishers.cpp
评论
0赞
Huy Le
3/8/2022
我需要实现隐藏在 .cpp 文件中
0赞
user12002570
3/8/2022
@HuyLe 为什么你没有在原来的问题中提到这个重要的细节?有关您的后续问题(即如何隐藏实现),请参阅是否可以隐藏模板类的实现?或提出单独的问题。
0赞
Huy Le
3/8/2022
那么这个链接中的解决方案是错误的吗?codeproject.com/Articles/48575/......
1赞
user12002570
3/8/2022
@HuyLe 他们的第一个解决方案似乎不起作用,演示。此外,在他们的第二个解决方案中,他们包含了一个源文件,这绝不是推荐的解决方案。TestTemp.cpp
评论