代码之家  ›  专栏  ›  技术社区  ›  backus sompnd

C的代码组织风格?[闭门]

  •  3
  • backus sompnd  · 技术社区  · 16 年前

    从未来编辑 当前位置回过头来看,这个问题相当愚蠢。我15岁,在我的学校没有CS。。。

    5 回复  |  直到 13 年前
        1
  •  18
  •   David Thornley    16 年前

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

    无论何时,只要您想使用隐藏实现实现接口,或者使用私有函数实现接口,就创建两个文件,如“foo.h”和“foo.c”。

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

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

    C语言与后来的语言没有任何相似之处,但是已经用它编写了很多非常好的程序。注意,对任何让人困惑的东西进行注释(在C语言中可能会有让人困惑的东西),并做好笔记。

        2
  •  9
  •   Doug T.    16 年前

    “功能无限的文件”

    您真正想要的是具有定义良好且功能有限的文件。这叫做 modular programming . 其思想是将基于功能的函数分组到单个编译单元中,并在标题中定义函数原型:

    Foo.h:

    int GetFoo();
    

    Foo.c:

    int GetFoo()
    {
       ...
    }
    

    这有点类似于将一组方法分组到单个类中的方式。主要的区别在于,在任何给定的时间,你都可能在做一件“这个”的事情,也可能没有。也就是说,您仍然可以用C语言进行基本上“面向对象”的编程。然而,您的对象将成为模块的一个参数。这里有一种方法:

    B.h:

    typedef int BAR_OBJ
    
    BAR_OBJ MakeBar();
    
    int GetBarSize(BAR_OBJ);
    
    void DoFooToBar(BAR_OBJ, ...)
    

       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
       }
    
        3
  •  4
  •   TrayMan    16 年前

    考虑一个名为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,但隐藏了实际实现myclass。这两个名字有两个名字,从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中实现,但它们涉及的内容更多。上面的模式,或者任何面向对象建模的模式,在C语言中并不总是做事情的最佳方式,所以尽量不要拘泥于以类为中心的思维方式。尽管如此,这种模式偶尔还是有用的。例如,libpng使用了与此类似的东西(它们也使用setjmp/longjmp执行“异常”,我建议不要这样做)。

        4
  •  3
  •   Wim ten Brink    16 年前

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

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

        5
  •  1
  •   Cat Plus Plus    16 年前