C的代码组织风格?

时间:2009-09-25 21:04:03

标签: c oop structure

我知道一些更高级别的语言,所有基于Web的(PHP,javascript,一些python)。我终于决定学习一门低级语言了,我决定和C一起去。问题是我使用的所有语言都是基于OOP。看作(基于我所做的研究)C没有类或继承。因此,我问你:我应该如何以有组织的方式在O中组织我的代码,而不必切换语言或只是拥有功能无穷无尽的文件?

从未来编辑:这个问题非常愚蠢。我15岁,在我的学校没有CS ......

5 个答案:

答案 0 :(得分:16)

C在代码组织方面没有提供太多帮助。有功能和文件。

每当您想要实现具有隐藏实现的接口,或者可能使用私有函数时,请创建两个文件,如“foo.h”和“foo.c”。

接口和/或公共函数是“foo.h”中的函数原型,函数用“foo.c”编写。此外,任何隐藏的实现或其他私有函数都在“foo.c”中,但标记为static,例如static int foo_internal_function(int i);。标记为static的函数只能在它们存在的文件中引用,而不能在其他任何文件中引用。

没有正式的命名空间,尽管使用前缀函数名称可以获得更多相同的效果,例如Foo_discombobulate_developers()。没有类,尽管你至少可以通过文件获得一些封装效果。没有可扩展的层次结构,只有文件和函数。

C在以后的语言组织附近没有任何地方,但是已经写了许多非常好的程序。小心,评论任何令人困惑的事情(在C中可能会有令人困惑的事情),并保持良好的记录。

答案 1 :(得分:8)

“具有无穷无尽功能的文件”

您真正想要的是具有明确定义且功能有限的文件。这称为modular programming。我们的想法是将基于功能的函数分组到单个编译单元中,并在标题中定义函数原型:

foo.h中:

int GetFoo();

foo.c的:

int GetFoo()
{
   ...
}

它有点类似于将一组方法分组到单个类中的方式。主要区别在于,您可能在任何特定时间都可以使用“这个”东西。也就是说,您仍然可以在C中进行基本上“面向对象”的编程。但是,您的对象将成为模块的参数。这是一种方法:

Bar.h:

typedef int BAR_OBJ

BAR_OBJ MakeBar();

int GetBarSize(BAR_OBJ);

void DoFooToBar(BAR_OBJ, ...)

Bar.c

   struct BarDetails
   {
      int isFree;
      int size;
      ...
      // other info about bar
   };

   static BarDetails arrayOfBars[...]; // 

   BAR_OBJ MakeBar()
   {
       // search BarDetails array, find free Bar    
   }

   int GetBarSize(BAR_OBJ obj)
   {
       return arrayOfBars[obj];
   }

   void DoFooToBar(BAR_OBJ, ...)
   {
      // lookup bar obj and do something
   }

答案 2 :(得分:4)

这是一种在C中弹出的模式,模仿OOP:

考虑一个名为MyClass的类。

/* MyClass.h or myclass.h */

#ifndef MYCLASS_H
#define MYCLASS_H

struct myclass_s;
typedef struct myclass_s myclass_t;

myclass_t * myclass_new();
void delete_myclass(myclass_t *);

    // Method int doMyStuff(int arg1,int arg2)
int myclass_doMyStuff(myclass_t *, int arg1, int arg2);

#endif //MYCLASS_H

头文件定义了myclass_t类型,但隐藏了实际的实现myclass_s。这有点尴尬要求有两个名称来自C在一个单独的命名空间中具有结构,而在C ++结构中与所有其他类型在同一名称空间中。该代码旨在兼容C和C ++。这是相应的.c文件:

/* MyClass.c or myclass.c */

#include "myclass.h" // Or MyClass.h

struct myclass_s {
   int exampleField;
};

myclass_t * myclass_new()
{
   myclass_t * o=(myclass_t*)malloc(sizeof(myclass_t));
   // Initialize o here.
   return o;
}

void myclass_delete(myclass_t * o)
{
   // Do any cleanup needed on o here.
   free(o);
}

int myclass_doMyStuff(myclass_t * o,int arg1,int arg2)
{
   // ...
}

在C中也可以进行继承和动态绑定,但它们更复杂一些。上面的模式,或任何模拟OOP的模式,并不总是用C做事的最佳方式,所以尽量不要挂在以类为中心的思维方式上。不过,这种模式偶尔也很有用。例如,libpng使用了接近这个的东西(他们也使用setjmp / longjmp做'异常',我建议反对)。

答案 3 :(得分:3)

好吧,如果你还想做一些OO,请使用C ++。

如果你真的只想使用C,没有任何OO,那么将你的逻辑划分为多个文件,并将每个源文件视为一个对象。因此,每个文件只能保存与该单一结构密切相关的结构和功能。

答案 4 :(得分:1)

OOP-ish C有GObject,但精心设计的结构化程序不应该比等效的OOP更难阅读/维护。