如何更好地组织C ++项目中的代码

时间:2010-01-21 19:35:40

标签: c++ namespaces code-organization

我目前正在尝试以更好的方式组织我的代码。

为此,我使用了名称空间,按组件对类进行分组,每个组都有一个已定义的角色和一些接口(实际上是抽象类)。

我发现它非常好,特别是当我不得不重写整个组件时,我对其他组件几乎没有影响。 (我相信使用一堆混合类和方法会更加困难)

然而,我并不是百分之百满意。特别是我想在接口,组件的公共面以及后面的实现之间做更好的分离。 我认为组件本身的“接口”应该更清晰,我的意思是新来者应该很容易理解他必须实现什么接口,他可以使用哪些接口以及实现的哪些部分。

很快,我将开始一个涉及多达5个开发者的更大项目,我想在这一点上明白我的想法。

那么你呢?你怎么做呢?你如何组织你的代码?

5 个答案:

答案 0 :(得分:4)

有两种常见的方法:

如果除了公共接口之外,您只需要一些辅助函数,只需将它们放在实现文件中的未命名的命名空间中:

// header:

class MyClass {
// interface etc.
};

// source file:

namespace {
    void someHelper() {}
}

// ... MyClass implementation

如果您发现自己想要隐藏成员函数,请考虑使用PIMPL惯用法:

class MyClassImpl; // forward declaration

class MyClass {
public:
    // public interface
private:
    MyClassImpl* pimpl;
}; 

MyClassImpl实现了这一功能,而MyClass则将对公共接口的调用转发给私有实现。

答案 1 :(得分:4)

  

特别是我想做得更好   接口之间的分离,   公众面对的组成部分,以及   他们在后面的实施。

我认为您正在寻找的是Facade模式:

  

facade是一个对象,它为更大的代码体提供了简化的接口,例如类库。 - 维基百科

如果您的班级中有复杂的互动,您可能还需要查看MediatorBuilder模式。

Pimpl成语(又名编译器防火墙)对隐藏实现细节和减少构建时间也很有用。当我不需要多态时,我更喜欢在接口类+工厂上使用Pimpl。但要注意不要过度使用它。不要将Pimpl用于通常在堆栈上分配的轻量级类型(如3D点或复数)。将它用于更大,寿命更长的类,这些类依赖于您希望向用户隐藏的其他类/库。

在大型项目中,当简单的前向声明执行时,不要在头文件中使用#include指令是很重要的。如果绝对必要,只在头文件中放入#include指令(更喜欢将#include放在实现文件中)。如果做得对,正确的#include规则将显着减少编译时间。 Pimpl习语可以帮助将#includes从头文件移动到相应的实现文件。

类和函数的连贯集合可以在它自己的命名空间中组合在一起,并放在源树的子目录中(子目录应该与库命名空间同名)。然后,您可以为该包创建静态库子项目/生成文件,并将其与主应用程序链接。这就是我认为UML术语中的“包”。在理想的包中,类彼此密切相关,但与包外的类松散相关。绘制包的依赖关系图是有帮助的,以确保没有周期性的依赖关系。

答案 2 :(得分:1)

您可能会发现Large Scale C++ Software Design中的一些建议很有用。它有点过时(1996年出版),但仍然很有价值,有关构造代码的指针,以最大限度地减少“单个头文件更改时重新编译世界”的问题。

答案 3 :(得分:0)

Herb Sutter关于“What's In a Class? - The Interface Principle”的文章提出了许多在设计界面时似乎没有想到的想法。它有点陈旧(1998年),但那里有一些有用的东西,但是。

答案 4 :(得分:-6)

首先声明你可以在一个字符串声明中使用它们的变量,也就是这样。

 char Name[100],Name2[100],Name3[100];
 using namespace std;
int main(){

 }

如果您有一长串可以在程序中使用的代码,那么它就是一个新功能。 likeso。

void Return(char Word[100]){
cout<<Word; 
cin.ignore();    
} 
int main(){ 
Return("Hello");
} 

我建议您将任何外部函数和声明放入头文件并链接它 likeso Dev-C ++ #include“Resource.h”