关于c ++:为什么模板类的实现和声明应该在同一个头文件中?

Why should the implementation and the declaration of a template class be in the same header file?

本问题已经有最佳答案,请猛点这里访问。

为什么模板类的实现和声明应该在同一个头文件中?你们谁能举例说明一下吗?


编译器需要访问整个模板定义(而不仅仅是签名),以便为模板的每个实例化生成代码,因此需要将函数的定义移动到头部。

有关更多详细信息,请阅读包含模型。


类模板的定义及其成员函数的实现必须对用不同类型实例化它的每个地方都可见。即,为了实例化myTemplate,您需要查看myTemplate的完整定义和实现。

最简单的方法是将模板及其成员函数的定义放在同一个头中,但还有其他方法。例如,可以将成员函数实现放在单独包含的文件中。然后您可以从第一个头部包含它,或者只在需要的地方包含实现文件。

例如,一个实践是在一个.cpp文件中显式地为不同的参数集实例化模板,并在头中声明这些实例化extern。这样,这些实例化就可以在其他源文件中使用,而不需要模板成员函数的实现可见。但是,除非包含实现文件,否则将无法使用其他模板参数集。

也就是说,如果您将myTemplatemyTemplate定义为extern,那么您可以很好地使用它们,但是如果myTemplate没有定义extern,那么没有实现就不能使用它。


他们不必这么做。

需要的是模板定义在实例化时是可见的(在使用它的地方),以便编译器可以在此时从模板派生类/函数。

但是,在模板类中使用两个头文件是非常常见的:

1
2
3
4
5
6
7
// 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; };

这允许那些不需要完整模板定义的人包括一个稍微轻一些的头,例如:

1
2
3
4
5
6
7
8
9
//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_ {};

这可以稍微加快编译时间。


在普通类的情况下,声明只够编译,相应的定义将被链接。

对于模板,编译器还需要定义来生成代码。

这种差异在C++ FAQ中得到了更好的解释。