假设我在collector.h
中的某处编写了类模板声明:
template <class T, int maxElements>
class collector {
T elements[maxElements];
int activeCount;
public:
collector();
void process();
void draw();
};
并在collector.cpp
中实施其三种方法:
template <class T, int maxElements>
collector<T, maxElements>::collector(){
//code here
}
template <class T, int maxElements>
void collector<T, maxElements>::process(){
//code here
}
template <class T, int maxElements>
void collector<T, maxElements>::draw(){
//code here
}
有没有办法不写template <class T, int maxElements>
和<T, maxElements>
对于每个功能的实现?这样的事情:
template <class T, int maxElements>{
collector<T, maxElements>::collector(){
//code here
}
void collector<T, maxElements>::process(){
//code here
}
void collector<T, maxElements>::draw(){
//code here
}
}
答案 0 :(得分:5)
将代码放在头文件中的类定义中。
[一旦尝试构建使用此类模板的代码,您最终可能会这样做。有关背景信息,请参阅here。来自@Pavel Minaev的被忽视的答案。]
答案 1 :(得分:1)
不,你每次都要写模板标题。
答案 2 :(得分:1)
通常,人们直接内联实现模板类。他们必须暴露出他们的全部资源(除非你明确地实例化这个地段),所以除此之外没有什么意义。
答案 3 :(得分:1)
有没有办法不编写模板和每个函数的实现?
不,没有在类模板的定义中内联定义模板成员,就没有办法做到这一点。
答案 4 :(得分:1)
以上许多人已经回答了你的问题的直接答案。
要了解有关最佳做法的更多信息,请参阅C++ Templates - The complete guide book的第6章。它讨论了哪个是声明和/或定义模板类,函数,成员函数的最佳位置:在.h / hpp或.cpp文件中。
答案 5 :(得分:1)
总有副本&amp;粘贴!
除非你有一个与你的编译器紧密耦合的智能C ++模板感知链接器,否则你必须在任何情况下将代码嵌入到标题中,问题就会消失。如果代码需要可移植,你可以在任何情况下都这样做。
如果你真的必须那么有一些有点不正面的预处理器宏解决方案:
#define COLLECTOR_TEMPLATE template <class T, int maxElements>
显式实例化.cpp文件中您希望需要的所有类型,以便编译器可以生成代码先验,链接器将引用templkates与预先实例化的定义匹配(参见http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13。但是,您将无法为新类型实例化模板。
对于单独编译模板以适用于任意实例化的类,编译器必须将模板源嵌入到目标文件中,然后当链接器需要特定的实例化来解析引用时,它必须提取该源并传递它返回编译器以生成实例化的目标代码,然后将其传递回链接器。这需要编译器和链接器一起工作,并且需要支持模板源嵌入的目标文件格式。
大多数工具链都不支持,因此您必须在标头中使用内联定义,将模板限制用于定义它的同一源文件,或者#include包含定义的.cpp ;所有这三个实际上都是相同的 - 在单个编译单元中使编译器可以看到完整的模板定义,但第一个是最常规和最灵活的解决方案。