使用本教程Makefile我想构建一个带有单独编译的简单程序,主要问题是IDE Eclpse Indigo C \ C ++(预期)或MinGW我无法编译文件。我得到的错误是:
undefined reference to double getAverage<int, 85u>(int (&) [85u])'
undefined reference to int getMax<int, 85u>(int (&) [85u])'
undefined reference to int getMin<int, 85u>(int (&) [85u])'
undefined reference to void print<int, 85u>(int (&) [85u])'
undefined reference to void sort<int, 85u>(int (&) [85u])'
undefined reference to void print<int, 85u>(int (&) [85u])'
main.cpp文件是这样的:
#include "Tools.h"
#include <iostream>
using namespace std;
int main(int argc,char* argv[])
{
int numbers[] = {1,-2,7,14,5,6,16,8,-2,7,14,5,6,16,8,-2,7,14,5,6,16,8,-2,7,14,5,6,16,8,-2,7,14,5,6,16,8,-2,7,14,5,6,16,8,-2,7,14,5,6,16,8,-2,7,14,5,6,16,8,-2,7,14,5,6,16,8,-2,7,14,5,6,16,8,-2,7,14,5,6,16,8,-2,7,14,5,6,16,8};
cout <<"Average = "<< getAverage(numbers) << endl;
cout <<"Max element = "<< getMax(numbers) << endl;
cout <<"Minimal element = "<< getMin(numbers) << endl;
print(numbers);
sort(numbers);
print(numbers);
return 0;
}
我有一个Tools.h文件:
#ifndef TOOLS_H_
#define TOOLS_H_
#include <iostream>
int getBigger(int numberOne,int numberTwo);
template <typename T,size_t N> double getAverage(T (&numbers)[N]);
template <typename T,size_t N> T getMax(T (&numbers)[N]);
template <typename T,size_t N> T getMin(T (&numbers)[N]);
/**
* Implementing a simple sort method of big arrays
*/
template <typename T,size_t N> void sort(T (&numbers)[N]);
/**
* Implementing a method for printing arrays
*/
template <typename T,size_t N> void print(T (&numbers)[N]);
#endif
答案 0 :(得分:2)
编译Tools.cpp时,编译器不知道您在main.cpp中使用的模板参数。因此,它编译与此模板无关的任何内容。
您需要在使用它们的编译单元中包含这些模板定义。 Tools.cpp文件经常被重命名为Tools.inl,以表明它既不是头文件也不是单独的编译单元。
编译单元“main.cpp”可能如下所示:
#include "tools.h"
#include "tools.inl"
main()
{
int number[] = {1,2,3};
getaverage(numbers);
}
由于编译器识别所需的特化,因此它可以从实现文件生成代码。
答案 1 :(得分:1)
对于大多数情况,harper的答案是恰当的。但为了完整起见,还应提及显式模板实例化。
当您在每个编译单元中包含实现时,您的模板类和函数将在所有这些中实例化和编译。有时,这是不可取的。如果您的模板类和函数非常复杂,那主要是由于编译时内存限制和编译时间。当您或您使用的库严重依赖模板元编程时,这将成为一个非常现实的问题。另一种情况可能是您的模板函数实现可能在许多编译单元中使用,并且当您更改实现时,您将被迫重新编译所有这些编译单元。
因此,在这些情况下,解决方案是包含类似tools.h
的标头文件,并拥有tools.cpp
,以实现模板。问题是,您应该为将在整个程序中使用的所有模板参数显式实例化模板。这是通过将以下内容添加到tools.cpp
:
template double getAverage<int,85>(int (&numbers)[85]);
注意:您显然必须对“85”执行某些操作,例如在头文件中定义并在tools.cpp
和main.cpp
答案 2 :(得分:0)
我发现这篇文章很有用:templates and header files
我在Tools.h文件中声明了该函数,并在那里包含了文件Tool.hpp,之后我在Tools.hpp文件中定义了它们。
答案 3 :(得分:0)
我没有尝试过编译.cpp和.c文件,但也许我的例子会有所帮助。
我有类似的问题,使用标准gcc编译两个单独的汇编文件.s 编译器和我实现如下:
gcc -m32 -o test test.s hello.s
-m32表示我正在编译32位代码
-o是输出文件(在我的示例中是“test”文件)
test.s和hello.s是我的源文件。 test.s是主文件,hello.s有helper函数。 (哦,要提到的是两个文件都在同一个目录中)