C ++ One Header Multiple Sources

时间:2011-08-24 03:52:43

标签: c++ header include

我有一个大班Foo 1

class Foo {
public:
    void apples1();
    void apples2();
    void apples3();

    void oranges1();
    void oranges2();
    void oranges3();
}

分割类不是 2 的选项,但foo.cpp文件已经变得相当大。在foo.h中保留类的定义并将函数的实现分为foo_apples.cppfoo_oranges.cpp是否存在任何重大设计缺陷。

这里的目标纯粹是为我自己和其他开发人员提供可读性和组织,这些开发人员在包含这个类的系统上工作。


1 “大”意味着大约4000行,而不是机器生成的 2 为什么呢?好吧,applesoranges实际上是在图表上运行但相互广泛使用的算法类别。它们可以分开,但由于工作的研究性质,我不断重新布线每种算法的工作方式,我发现对于我而言(在早期阶段)并不符合经典的OOP原则。

4 个答案:

答案 0 :(得分:5)

  

在foo.h中保留类的定义以及将函数的实现分成foo_apples.cpp和foo_oranges.cpp是否存在任何主要的设计缺陷。

选择nits:在foo.h中保留类的声明并拆分方法的定义是否存在任何重大设计缺陷进入foo_apples.cpp和foo_oranges.cpp。

1)苹果和橘子可能使用相同的私人程序。一个例子就是在匿名命名空间中找到的实现。

在这种情况下,一个要求是确保您的静态数据不是多次定义的。如果内联函数不使用静态数据(尽管它们的定义可以多次导出),它们并不是真正的问题。

为了克服这些问题,您可能会倾向于利用类中的存储 - 这可能会通过增加本来会隐藏的数据/类型来引入依赖关系。在任何一种情况下,它都会增加复杂性或迫使您以不同的方式编写程序。

2)它增加了静态初始化的复杂性。

3)它增加了编译时间

我在真正大型程序中使用的替代方案(其中包括许多开发人员讨厌)是创建导出的本地标题的集合。这些标头只对包/库可见。在您的示例中,可以通过创建以下标题来说明:Foo.static.exported.hpp(如果需要)+ Foo.private.exported.hpp(如果需要)+ Foo.apples.exported.hpp + Foo.oranges.exported.hpp

然后你会像这样编写Foo.cpp:

#include "DEPENDENCIES.hpp"
#include "Foo.static.exported.hpp" /* if needed */
#include "Foo.private.exported.hpp" /* if needed */
#include "Foo.apples.exported.hpp"
#include "Foo.oranges.exported.hpp"

/* no definitions here */

您可以根据需要轻松调整这些文件的分割方式。如果你使用c ++约定编写你的程序,那么巨大的TU很少会发生冲突。如果你像C程序员一样编写(很多全局变量,预处理程序滥用,低警告级别和自由声明),那么这种方法会暴露出许多你可能不会纠正的问题。

答案 1 :(得分:4)

从技术角度来看,完全没有惩罚,但我从未在实践中看到它。这只是一个风格问题,并且在这种精神上,如果它能帮助你更好地阅读课程,那么你就不会因为不使用多个源文件而对自己造成伤害。

编辑:除此之外,您是否使用鼠标中键滚动浏览源代码?正如其他人已经提到的那样,IDE几乎普遍允许您右键单击函数声明,然后转到定义。即使您的IDE不是这种情况,并且您使用记事本或其他东西,它将至少具有ctrl + f。没有找到并替换我就会迷失。

答案 2 :(得分:2)

是的,您可以在一个头文件中定义类,并在多个源文件中拆分函数实现。这通常不是常见的做法,但是它会起作用并且不会产生任何管理费用。

如果这样做的目的只是简单的可读性,那么也许这样做并不是一个好主意,因为将类函数定义放在多个源文件中并且可能只会让某人感到困惑并不常见。 / p>

答案 3 :(得分:0)

实际上我没有看到任何拆分实现的理由,因为其他开发人员应该使用接口,而不是实现。

此外,任何普通的IDE都可以轻松地从函数声明跳转到它的defenition。所以没有理由手动搜索函数实现。