我正在阅读一本较旧的数据结构书,它说当你进行模板类编程时,你应该在.h文件的末尾包含.cpp。
据我所知,您必须在.h文件中为任何模板类成员函数执行完整的函数实现 - 这是由于模板编译器的工作方式。
我教过的唯一函数可以放在模板类的实现文件中,是模板特化函数,即:template<> Class<Type>::function_name()
。
为什么这本书建议在.h结束时加入.cpp?这只是一种将实现分离到不同文件,同时让它们用标题编译的方法吗?如果是这样,你会在哪里放置真正的专业 - 我猜他们不能进入标题所包含的.cpp。
答案 0 :(得分:10)
作者很可能更喜欢在不同的文件中使用声明和定义,我猜这是因为它可以更容易地在声明和定义之间跳转。
但是“cpp”文件扩展名有点令人困惑。通常这些文件被称为“内联C ++”的“ipp”。
答案 1 :(得分:3)
这可能是古老的说法,我认为您对实施和声明分离的分析是正确的。回到编写这本特定的书时,作者可能认为cpp文件是定义所在的文件,h文件是声明所在的文件。由于重复的定义,将真正的显式特化放入前一个文件中对链接器来说自然是致命的(或至少是无用的)。如今,我会避免命名定义文件.cpp。
答案 2 :(得分:2)
首先,没有规则你必须拥有的实现
您的.h
(或.hpp
或.hh
)文件中的模板;事实上,对于任何事情
但最简单的模板,我建议不要这样做。你做
无论文件如何,都必须包含实现。什么的
作者可能想到的是将实现放在.cpp
中
文件,并包括。我建议找一个不同的名字,
但是,因为大多数人(以及一些IDE)会认为你应该这样做
编译所有.cpp
个文件。 .cc
和.hh
的常见惯例
对于模板,源和标头的常用扩展名为.tcc
实现;在Windows世界中(.cpp
几乎是通用的),
我推荐像.tpp
这样的东西。
请注意,最早的模板实现需要
实施在.cpp
。这些实现不需要
但是,(或允许)将其包括在内;编译器搜索了
与.cpp
(或.cc
)文件相对应的.hpp
(或.hh
)
模板类定义或函数声明出现了,和
生成一个包含它的虚拟源文件(以及其他任何内容
是必要的。)
答案 3 :(得分:0)
据我所知,你必须在你的网站上做全功能实现 .h文件用于任何模板类成员函数 - 这是由于方式 模板编译器工作。
可能是本书假设您在.cpp
文件中有完整的功能实现。
如果完全特化是在cpp文件中,则它们不应包含在头文件中。如果你这样做,很可能它不会编译。因为编译器会看到与头文件相同功能的多个定义通常会包含在多个源文件中。
答案 4 :(得分:0)
如果要使用模板,则必须在实例化模板的TU中显示整个模板定义。因此,您只需将完整定义放在头文件中即可。
只有当你真的想要保持类定义和类成员函数体分开时,你才可能想把这些函数定义放到一个单独的文件中。但是,上述规则仍然适用,因此您必须将单独的文件与标题一起包含在内,以便任何人都可以使用该模板。
这是一个品味问题。如果成员函数体很短,您也可以将它们内联定义。还要记住,在类定义中定义的函数是隐式声明的inline
,而如果你单独编写实体,则必须明确指定。
部分专门化的模板仍然是模板,因此适用相同的规则。
一个完全专业化的类模板只是一个普通的类,所以你可以这样对待:
// FooInt.hpp
template <typename> class Foo;
template <> class Foo<int>
{
// your class here
};
您可能想到的一件事是“显式模板实例化”,即la template class Foo<int>;
。那是另一回事;如果您有兴趣使用它,请发表评论。