我在Array.hpp
文件中有一些类似这样的代码
template <typename T>
class Array {
private:
T *_array;
int _arrSize;
public:
Array<T>();
Array<T>(unsigned int n);
...
};
然后在Array.cpp
文件中,我就这样
#include "Array.hpp"
template <typename T>
Array<T>::Array<T>(){};
template <typename T>
Array<T>::Array<T>(unsigned int n) : _arrSize(n) {
T *a = new T[n];
for (unsigned int i = 0; i < n; i++) {
a[i] = 0;
}
this->_array = a;
};
...
然后简单如
int main() {
Array<int> g(2);
return 0;
}
但是当我尝试使用clang++ -Wall -Wextra -Werror -std=c++98 *.c
进行编译时,会出现此错误
Array.cpp:16:11: error: out-of-line constructor for 'Array' cannot have template arguments Array<T>::Array<T>(){}; ^ ~~~ Array.cpp:19:11: error: out-of-line constructor for 'Array' cannot have template arguments Array<T>::Array<T>(unsigned int n) : _arrSize(n) { ^ ~~~
我不确定自己在做什么错
答案 0 :(得分:6)
正确的语法是
Array<T>::Array()
不是
Array<T>::Array<T>()
相关说明,在.cpp文件中实现模板是almost always wrong。
您仍然应该使用std::vector
。
答案 1 :(得分:4)
您的定义原型是错误的:
template <typename T>
Array<T>::Array<T>(){};
Visual Studio 2015编译器发出此警告,使错误更加清楚:
warning C4812: obsolete declaration style: please use 'Array<T>::Array' instead
因此您的实现应如下所示:
template <typename T>
Array<T>::Array(){};
template <typename T>
Array<T>::Array(unsigned int n) : _arrSize(n) {
...
};
...
这是因为构造函数本身不是“模板化”的。
如果声明看起来像这样。
template <typename T>
class Array<T>
{
template <typename Y>
Array<T>(Y n);
};
您将需要此附加模板参数,但需要另一个模板行:
template <typename T>
template <typename Y>
Array<T>::Array<Y>(Y n){};
但是,代码的另一个问题是您从包含文件中隐藏了模板实现,因此编译器无法实例化它。
当前,您的main.cpp
无法看到构造函数的实现。它只会在标题中看到声明。
您有不同的选择:
Array.cpp
中的模板,即可使用严格的类型子集来限制类的使用:
template class Array<int>;
在文件范围内。对于容器类型,这似乎不是一个选择。Array.cpp
(但我会在标头末尾将其称为Array_Impl.hpp
(但您必须小心,因为cpp中的所有内容将在标题以及包含标题的所有文件中可见)