我有一个模板类:
template<typename A, typename B>
class A {
};
在另一个.h文件中
template<typename A, typename B>
class A; //forward declaration
我怎么能在这里宣布m_A
?我继续得到{+ 1}}的C ++禁止声明,没有类型错误:
A
答案 0 :(得分:6)
如果您不知道要在A
内部实例化B
的类型,那么您还必须使用B
template<typename A1, typename B1>
class B
{
A<A1, B1>* m_A;
};
或者你必须将A
实例化为特定类型,即
class B
{
A<Type_1, Type_2>* m_A;
};
答案 1 :(得分:5)
使用m_A
的某些特定类型声明A
:
class B
{
A<int, char>* m_A;
}
如果你不知道先验在m_A
声明中应该使用哪些类型,那么B
可能需要是模板类而你在m_A
的声明中使用这些类型参数。
答案 2 :(得分:2)
模板是很好的小怪物。模板定义必须在实例化地点为编译器提供,因此最常见的模式是在头文件中定义模板,以便使用模板化方法的每个翻译单元(从而实例化它们)将有权访问该定义。
或者,您可以在单个翻译单元中提供模板定义,但是您必须确保为在整个程序中使用它的所有类型实例化模板。
// header
template <typename T> struct A
{
void foo( T );
}
// single translation unit
#include "header"
template <typename T> // template member definitino
void A<T>::foo( T x ) {
std::cout << "A(" << x << ")" << std::endl;
}
template struct A<int>; // explicit instantiation for int
template struct A<double>; // explicit instantiation for double
// main
#include "header"
int main() {
A<int> ai;
ai.foo( 5.5 ); // will print 5 (int rounded down)
A<double> ad;
ad.foo( 5.5 ); // will print 5.5
A<char> ac;
ac.foo( 'a' ); // linker error, A<char>::foo undefined
}
因为通常模板意味着通过程序与任何类型一起使用,所以在单个翻译单元中定义模板方法并使用显式实例化不是一个好主意。另一方面,在少数情况下,您需要控制实例化模板的类型集,或者在其他一些情况下(减少大型编译时间[*]),您可能希望遵循第二种方法。但同样,在一般情况下,在标题中定义成员函数更简单,并且再次定义它们在类定义中更简单。
[*]模板在使用它们的所有翻译单元中编译,这意味着如果您在5个不同的翻译单元中实例化A<int>::foo
,编译器将编译5次,然后链接器将丢弃4个实例化。在模板复杂的某些情况下,在一个翻译单元中编译一次并从其他翻译单元中调用它可能是有利的。请注意,通过显式实例化,所有成员函数都被编译,而使用隐式实例化(在使用地点),只有那些实际使用的成员才会被编译,因此依赖于在这种情况下,显式实例化可能比隐式实例化更成本(在具有许多成员的类中)
答案 3 :(得分:-1)
模板&lt; typename A&gt; void B&lt; A&gt; :: function() { }
Btw, do not separate definitions and declarations while writing a template class.
编辑: 改变了&lt;到&amp; lt;和&gt;到&amp; gt; 在该代码看起来像之前:
模板 void B :: function() { }