2015-11-27 48 views
0

我是C++新手,在解決我遇到的未定義引用問題時遇到困難。我試圖創建一個測試類,它作爲輸入數組構造函數,和一切似乎如果我把一切都位於一個文件,如下工作:C++未定義引用構造函數錯誤?

main.cpp 

#include <iostream> 

class Test 
{ 
    public: 
     template<typename T,int SIZE> 
     Test(T (&array)[SIZE]); 
}; 

template<typename T,int SIZE> 
Test::Test(T (&array)[SIZE]) 
{ 
    std::cout << "Array constructor was called" << std::endl; 
    std::cout << "Size of array is: " << SIZE << std::endl; 
} 

int main() 
{ 
    int myIntArray[10];  
    Test myTest(myIntArray); 
    return 0; 
} 

當我運行這個例子,我得到的以下的輸出:

Array constructor was called 
Size of array is: 10 

然而,當我打破了這個例子爲以下三個文件:

Test.h

class Test 
{ 
    public: 
     template<typename T,int SIZE> 
     Test(T (&array)[SIZE]); 
}; 

Test.cpp的

#include "Test.h" 
#include <iostream> 

template<typename T,int SIZE> 
Test::Test(T (&array)[SIZE]) 
{ 
    std::cout << "Array constructor was called" << std::endl; 
    std::cout << "Size of array is: " << SIZE << std::endl; 
} 

的main.cpp

#include "Test.h" 
#include <iostream> 

int main() 
{ 
    int myIntArray[10];  
    Test myTest(myIntArray); 
    return 0; 
} 

我收到an undefined reference to Test::Test<int, 10>(int (&) [10])'。我不完全確定我做錯了什麼,並且正在想我可能忽略了一些事情。任何洞察力將不勝感激。感謝您的幫助。

+1

請參閱http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – clcto

+0

@clcto感謝您的參考。我將不得不進一步詳細研究模板。 –

回答

1

問題是你正在分開你的模板函數聲明和模板函數定義。當您定義一個模板函數時,您的函數聲明及其定義必須位於同一位置。如果不位於同一位置,則應在.tpp文件中定義模板函數,然後將該.tpp文件包含在聲明模板函數的頭文件中。

這是什麼要求?與事先知道參數類型的常規函數​​不同,編譯器會爲每次調用具有不同類型的函數加載一個版本的模板函數。所以,你的情況,當你這樣做,

int main() 
{ 
    int myIntArray[10];  
    Test myTest(myIntArray); 
    return 0; 
} 

編譯器是什麼,定義一個函數的定義,

Test::Test(int (&array)[SIZE]) 
{ 
    std::cout << "Array constructor was called" << std::endl; 
    std::cout << "Size of array is: " << SIZE << std::endl; 
} 

,這加載到內存中。 但是,如果編譯器必須執行此操作,則它必須在函數的頭文件中查看聲明時訪問該函數的定義。將函數定義在單獨的.cpp文件中時,編譯器無法訪問函數的定義,因此無法基於用戶輸入定義函數並將其加載到內存中。

就像我剛纔提到的,如果你想從定義中分離出實現,你可以把模板函數的定義放在一個.tpp文件中(這是一個專門用於模板函數定義的文件) 。H。像這樣的東西。

Test.h:

class Test 
{ 
    public: 
     template<typename T,int SIZE> 
     Test(T (&array)[SIZE]); 
}; 

#include "Test.tpp" 

Test.tpp

#include <iostream> 

template<typename T,int SIZE> 
Test::Test(T (&array)[SIZE]) 
{ 
    std::cout << "Array constructor was called" << std::endl; 
    std::cout << "Size of array is: " << SIZE << std::endl; 
} 

的main.cpp

#include <iostream> 

template<typename T,int SIZE> 
Test::Test(T (&array)[SIZE]) 
{ 
    std::cout << "Array constructor was called" << std::endl; 
    std::cout << "Size of array is: " << SIZE << std::endl; 
} 

希望這有助於。

0

試試這個:

的main.cpp

#include <iostream> 

template<typename T> 
class Test 
{ 
    public: 
    Test(T *array, int SIZE) 
    { 
     std::cout << "Array constructor was called" << std::endl; 
     std::cout << "Size of array is: " << SIZE << std::endl; 
    } 
}; 

Test.h

#include <iostream> 

template<typename T> 
class Test 
{ 
    public: 
    Test(T *array, int SIZE) 
    { 
     std::cout << "Array constructor was called" << std::endl; 
     std::cout << "Size of array is: " << SIZE << std::endl; 
    } 
}; 

你可能想使用std::vector代替陣列。這樣,在使用之前,並不總是需要引用數組的大小。管理起來要容易得多。

此外,模板類最好在其頭文件中實現。

+0

那麼他們不一定是,但這是最常見的要求。 –