2015-11-27 52 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

那么他们不一定是,但这是最常见的要求。 –