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

时间:2012-07-19 20:52:21

标签: c++ templates build include

在我正在进行的项目中,我有一个相当大的模板化课程,我已经实现了这样:

我有我的头文件

// 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行文件。文件本身在逻辑上是相当有条理的,仅包含嵌套类的实现或一组相互关联的成员函数。

我的问题是,这件事情已经完成了吗?前几天当我向某人展示时,我得到了一个奇怪的反应,所以我想知道这是不是一种不好的做法,或者是否有一种更好,更常用的方式来完成这样的事情。

4 个答案:

答案 0 :(得分:5)

通常不包含cpp文件(这种情况有限且充满异国情调),这可能是你得到奇怪外观的原因。

通常,通过将实现移至.impl甚至.h文件而非cpp文件来完成此分离。

不,分离模板的实现并在标题中包含文件没有任何问题。

答案 1 :(得分:4)

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

答案 2 :(得分:2)

参与了有数千个或更多文件的C / C ++项目,这是我一般观察到的做法:

  1. 将类定义保留在头文件中。不要在头文件中添加任何实现。内联函数和模板是例外。我最终会谈到这一点。
  2. 将所有函数和方法实现保存在.c或.cpp文件中。
  3. 有这样做的基本原因。

    1. .h文件充当任何人使用您在代码中实现的类/函数/以及其他数据结构和API的参考点。任何不了解类结构的人都会先参考.h。
    2. 您可以分发仅显示.h文件的库,而不会泄露您的实际实现。通常他们会提供外部API(再次使用.h文件),它们是库中任何代码的唯一入口点,如果他们希望共享代码,可供第三方使用。
    3. 如果在多个位置包含.c或.cpp文件 - 在编译过程中不会看到任何错误 - 但链接器会因为重复符号而抱怨。因为它包含了.c / .cpp文件中所有这些函数/方法部分的多个副本。
    4. <强>例外

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

        A级; A.my_inline_method();

      2. 如果编译此cpp文件时编译器看不到my_inline_method()为内联函数,则不会内联此函数。

        1. 模板在编译时类似于内联方法 - 当模板的代码需要由.cpp中的编译器生成时,它需要知道该模板的整个实现。由于模板代码生成是编译时而非运行时。
        2. 我已经提到了这背后更为常见的哲学。如果我错过了,请随意编辑此答案以添加更多答案。

          有关模板资料的更多信息:Why can templates only be implemented in the header file?

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

答案 3 :(得分:1)

我正在回答我自己的问题,补充说模板实现的某种标准扩展似乎是.tcc。它是recognized by github's syntax highlighter,也在gcc手册页中提到:

  

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

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