2012-01-30 153 views
2

使用本教程Makefile我想用獨立的編譯構建一個簡單的程序,主要問題是IDE Eclpse Indigo C \ C++(預測)或MinGW I無法編譯這些文件。這是我得到的錯誤是:使用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 
+2

函數的定義在哪裏?由於您使用的是模板,因此您應該將其包含在標題(.h)中。請參閱[爲什麼模板只能在頭文件中實現?](http://stackoverflow.com/q/495021/20984)。 – 2012-01-30 14:15:32

+0

函數的定義在Tools.cpp文件中。 – 2012-01-30 14:22:04

回答

2

當你編譯工具。 cpp你的編譯器不知道你在main.cpp中使用過的模板參數。因此它不編譯任何與這個模板相關的東西。

您需要在使用它們的編譯單元中包含這些模板定義。 Tools.cpp文件通常重命名爲Tools.inl,以表明它既不是頭文件也不是單獨的編譯單元。

編譯單元「的main.cpp」看起來是這樣的:

#include "tools.h" 
#include "tools.inl" 

main() 
{ 
    int number[] = {1,2,3}; 
    getaverage(numbers); 
} 

由於編譯器識別所需要的專業化它可以生成從執行文件中的代碼。

+0

我將Tools.cpp擴展名更改爲Tools.ini ,但未定義的函數引用仍然存在問題。 – 2012-01-31 10:21:00

+0

但是當我在頭文件中定義函數時,一切都很好。 – 2012-01-31 10:26:54

+0

可以在頭文件中定義函數,因爲它們是內聯函數。代碼在您的代碼需要實現時生成。如果您認爲頭文件描述了接口並且不應該混淆實現細節,則只需要一個單獨的文件。 – harper 2012-01-31 15:26:13

0

我發現這篇文章是有用的:templates and header files

我宣佈在的Tools.h文件的功能,包括有文件Tool.hpp並在此之後我在Tools.hpp文件中定義它們。

1

對於大多數情況下,harper的回答是適當的。但爲了完整性,還應該提到顯式模板實例化。

當您在每個編譯單元中包含實現時,您的模板類和函數將被實例化並編譯到所有編譯單元中。有時候,這是不可取的。這主要是由於編譯時內存限制和編譯時間,如果你的模板類和函數非常複雜。當你或者你使用的庫嚴重依賴於模板元編程時,這成爲一個非常真實的問題。另一種情況可能是您的模板函數實現可能在許多編譯單元中使用,並且當您更改實現時,您將被迫重新編譯所有這些編譯單元。

因此,這些情況下的解決方案是包含一個類似tools.h的頭文件,並且有一個tools.cpp實現模板。問題在於,您應該明確地實例化您的模板,以獲取將在整個程序中使用的所有模板參數。

template double getAverage<int,85>(int (&numbers)[85]); 

注:這是通過添加以下到tools.cpp完成顯然,你必須做一些事「85」,如在頭文件中定義它並使用它跨越tools.cppmain.cpp

+0

是的,我忘了提這個。我認爲這是一個故意的對象,要求有一個「單獨編譯」。 – harper 2012-02-01 17:23:59

0

我還沒有嘗試編譯.cpp和.c文件,但也許我的例子會有所幫助。

我有類似的問題編譯兩個單獨的程序集文件。S於與標準的gcc 編譯MinGW和我實現,如下所示:

gcc -m32 -o test test.s hello.s 

-m32意味着即時編譯32位代碼

-o是輸出文件(這在我的例子是「測試「文件)

test.s和hello.s是我的源文件。 test.s是主文件,hello.s具有幫助函數。 (哦,要提到的是兩個文件都在同一個目錄中的事實)