This question already has an answer here:
这个问题已经有了答案:
- Why can templates only be implemented in the header file? 13 answers
- 为什么模板只能在头文件中实现?13个答案
Why should the implementation and the declaration of a template class be in the same header file? Could any of you explain it by example?
为什么模板类的实现和声明应该放在同一个头文件中?你们谁能举例说明一下吗?
4 个解决方案
#1
24
The compiler needs to have access to the entire template definition (not just the signature) in order to generate code for each instantiation of the template, so you need to move the definitions of the functions to your header.
编译器需要访问整个模板定义(不仅仅是签名),以便为模板的每个实例化生成代码,因此需要将函数的定义移动到头部。
For more details read about The Inclusion Model.
有关包含模型的更多细节,请参阅。
#2
6
The definition of a class template and the implementation of its member functions has to be visible to every place that instantiates it with a distinct type. i.e. in order to instantiate myTemplate<int>
you need to see the full definition and implementation of myTemplate
.
类模板的定义及其成员函数的实现必须对使用不同类型实例化它的每个地方都可见。例如,为了实例化myTemplate
The easiest way to do this is to put the definition of the template and its member functions in the same header, but there are other ways. For example, you could put the member function implementations in a separate file that was included separately. You could then include it from the first header, or only include the implementation file where you needed it.
最简单的方法是将模板及其成员函数的定义放在同一个头中,但是还有其他方法。例如,可以将成员函数实现放在单独的文件中。然后可以从第一个头文件中包含它,或者只包含需要它的实现文件。
For example, one practise is to explicitly instantiate a template for distinct set of parameters in one .cpp file and declare those instantiations extern
in the header. This way, those instantiations can be used in other source files without requiring the implementation of the template member functions to be visible. However, unless you include the implementation file you won't be able to use other sets of template parameters.
例如,一个实践是在一个.cpp文件中显式地为不同的参数集实例化一个模板,并在头中声明那些实例化的外部。通过这种方式,这些实例化可以在其他源文件中使用,而不需要模板成员函数的实现是可见的。但是,除非包含实现文件,否则不能使用其他模板参数集。
i.e. if you have myTemplate<int>
and myTemplate<std::string>
defined as extern
then you can use them fine, but if myTemplate<double>
is not defined extern
then you cannot use that without the implementation.
例如,如果你有myTemplate
#3
4
They don't have to.
他们不需要。
What is necessary is for the template definition to be visible at the point of instantiation (where it's used) so that the compiler can derive the class / function from the template at this point.
需要的是模板定义在实例化点(使用模板的地方)是可见的,这样编译器就可以从模板中派生类/函数。
However it is extremely common to use two header files for template classes:
但是,在模板类中使用两个头文件是非常常见的:
// foo_fwd.hpp
template <typename T, typename U> struct Foo;
// foo.hpp
#include "foo_fwd.hpp"
template <typename T, typename U> struct Foo { typedef std::pair<T,U> type; };
This allows those who do not need the full template definition to include a somewhat lighter header, for example:
这允许那些不需要完整模板定义的人包括一个稍微轻一些的标题,例如:
//is_foo.hpp
#include <boost/mpl/bool.hpp>
#include "foo_fwd.hpp"
template <typename Z>
struct is_foo: boost::mpl::false_ {};
template <typename T, typename U>
struct is_foo< Foo<T,U> >: boost::mpl::true_ {};
which can speed up compilation-time a bit.
它可以稍微加快编译时间。
#4
4
In the case of a normal class, the declaration is just enough for compilation, and the corresponding definitions will be linked.
在普通类的情况下,声明仅够编译,相应的定义将被链接。
In the case of templates, the compiler also needs the definition to generate the code.
对于模板,编译器还需要定义来生成代码。
The difference is better explained in the C++ FAQ.
不同之处在c++ FAQ中有更好的解释。
#1
24
The compiler needs to have access to the entire template definition (not just the signature) in order to generate code for each instantiation of the template, so you need to move the definitions of the functions to your header.
编译器需要访问整个模板定义(不仅仅是签名),以便为模板的每个实例化生成代码,因此需要将函数的定义移动到头部。
For more details read about The Inclusion Model.
有关包含模型的更多细节,请参阅。
#2
6
The definition of a class template and the implementation of its member functions has to be visible to every place that instantiates it with a distinct type. i.e. in order to instantiate myTemplate<int>
you need to see the full definition and implementation of myTemplate
.
类模板的定义及其成员函数的实现必须对使用不同类型实例化它的每个地方都可见。例如,为了实例化myTemplate
The easiest way to do this is to put the definition of the template and its member functions in the same header, but there are other ways. For example, you could put the member function implementations in a separate file that was included separately. You could then include it from the first header, or only include the implementation file where you needed it.
最简单的方法是将模板及其成员函数的定义放在同一个头中,但是还有其他方法。例如,可以将成员函数实现放在单独的文件中。然后可以从第一个头文件中包含它,或者只包含需要它的实现文件。
For example, one practise is to explicitly instantiate a template for distinct set of parameters in one .cpp file and declare those instantiations extern
in the header. This way, those instantiations can be used in other source files without requiring the implementation of the template member functions to be visible. However, unless you include the implementation file you won't be able to use other sets of template parameters.
例如,一个实践是在一个.cpp文件中显式地为不同的参数集实例化一个模板,并在头中声明那些实例化的外部。通过这种方式,这些实例化可以在其他源文件中使用,而不需要模板成员函数的实现是可见的。但是,除非包含实现文件,否则不能使用其他模板参数集。
i.e. if you have myTemplate<int>
and myTemplate<std::string>
defined as extern
then you can use them fine, but if myTemplate<double>
is not defined extern
then you cannot use that without the implementation.
例如,如果你有myTemplate
#3
4
They don't have to.
他们不需要。
What is necessary is for the template definition to be visible at the point of instantiation (where it's used) so that the compiler can derive the class / function from the template at this point.
需要的是模板定义在实例化点(使用模板的地方)是可见的,这样编译器就可以从模板中派生类/函数。
However it is extremely common to use two header files for template classes:
但是,在模板类中使用两个头文件是非常常见的:
// foo_fwd.hpp
template <typename T, typename U> struct Foo;
// foo.hpp
#include "foo_fwd.hpp"
template <typename T, typename U> struct Foo { typedef std::pair<T,U> type; };
This allows those who do not need the full template definition to include a somewhat lighter header, for example:
这允许那些不需要完整模板定义的人包括一个稍微轻一些的标题,例如:
//is_foo.hpp
#include <boost/mpl/bool.hpp>
#include "foo_fwd.hpp"
template <typename Z>
struct is_foo: boost::mpl::false_ {};
template <typename T, typename U>
struct is_foo< Foo<T,U> >: boost::mpl::true_ {};
which can speed up compilation-time a bit.
它可以稍微加快编译时间。
#4
4
In the case of a normal class, the declaration is just enough for compilation, and the corresponding definitions will be linked.
在普通类的情况下,声明仅够编译,相应的定义将被链接。
In the case of templates, the compiler also needs the definition to generate the code.
对于模板,编译器还需要定义来生成代码。
The difference is better explained in the C++ FAQ.
不同之处在c++ FAQ中有更好的解释。