#include.cpp模板实现文件是一种不好的做法吗?

Is #include'ing .cpp template implementation files a bad practice?

本文关键字:一种 cpp 实现 文件 #include      更新时间:2023-10-16

在我正在进行的一个项目中,我有一个相当大的模板类,我已经实现如下:

我有我的头文件

// MyBigClass.h
#ifndef MYBIGCLASS_H
#define MYBIGCLASS_H
template <typename T>
class MyBigClass {
   /* -- snip -- */
};
#include "MyBigClass.cpp"
#include "MyBigClass_iterator.cpp"
#include "MyBigClass_complicatedFunctionality_1.cpp"
#include "MyBigClass_complicatedFunctionality_2.cpp"
#endif

然后我所有的实现文件基本上都是这样的:

// MyBigClass_foobar.cpp
template <typename T>
void MyBigClass<T>::member_1(){
   /* -- snip -- */
}
template <typename T>
int MyBigClass<T>::member_2(int foo, T & bar){
   /* -- snip -- */
}
// etc, etc

main.cpp中,我只包含了MyBigClass.h,一切都很好地工作和编译。我之所以将实现拆分为许多文件,是因为我更喜欢处理三到四个200-400行的文件,而不是一个1200行的文件。文件本身在逻辑上组织得相当好,例如只包含嵌套类的实现,或一组相互关联的成员函数。

我的问题是,这是已经完成的事情吗?前几天当我把这个展示给别人时,我有一个奇怪的反应,所以我想知道这是不是一个糟糕的做法,或者是否有更好、更常见的方法来完成这样的事情。

按照惯例,通常不包括cpp文件(这样做时会有有限的和奇异的情况),这可能是你得到奇怪外观的原因。

通常,这种分离是通过将实现移动到.impl甚至.h文件而不是cpp文件来完成的。

不,分离模板的实现并将文件包含在头中并没有错。

所以。。。包含.cpp是一种不好的做法,但是什么阻止您使用头文件而不是.cpp?例如,提升使用.ipp文件。。。

我曾处理过包含数千个或更多文件的C/C++项目,这是我通常观察到的做法:

  1. 将类定义保留在头文件中。不要在头文件中添加任何实现。内联函数和模板除外。我最终会明白的
  2. 将所有函数和方法实现保存在.c或.cpp文件中

这样做有其根本原因

  1. .h文件是任何人使用您在代码中实现的类/函数/和其他数据结构和API的参考点。任何不知道类结构的人都会先引用.h
  2. 您可以分发一个只显示.h文件的库,而不显示您的实际实现。通常,他们会提供外部API(同样在.h文件中),这些API是库中任何代码的唯一入口点,如果第三方希望共享代码,则可以使用这些API
  3. 如果在多个位置包含一个.c或.cpp文件(在编译过程中不会看到任何错误),但链接器会解决重复符号的问题。由于它有多个您包含的.c/.cpp文件中所有这些函数/方法的副本

异常

  1. 内联函数实现需要存在于.h文件中才能有效。有些情况下,编译器可能会自动决定一段代码可以内联,但在某些情况下,它需要内联关键字的存在注意:我在这里只谈论后者编译器只有在看到inline关键字时才会内联任何函数。换句话说,如果.cpp有以下代码:

    A类;A.my_inline_method();

如果在编译此cpp文件时,my_inline_method()作为内联函数对编译器不可见,则它将不会内联此函数。

  1. 当涉及到编译时,模板类似于内联方法——当模板的代码需要由编译器在使用它的.cpp中生成时——它需要知道该模板的整个实现。由于模板代码生成是编译时和NOT运行时生成的

我已经提到了这背后更常见的哲学。如果我错过了,请随意编辑此答案以添加更多内容。

关于模板的更多信息:为什么模板只能在头文件中实现?

编辑:根据@Forever的评论进行了更改,以避免歧义。

我在回答自己的问题时补充说,模板实现的一个标准扩展似乎是.tcc。它被github的语法高亮器识别,也在gcc手册页中提到:

C++源文件通常使用后缀.C.cc.cpp.CPP.c++.cp.cxx中的一个;C++头文件通常使用.hh.hpp.H或(对于共享模板代码).tcc

如果我误解了.tcc扩展的预期用途,请告诉我,我会删除这个答案!

相关文章: