我知道一些更高级别的语言,所有基于Web的(PHP,javascript,一些python)。我终于决定学习一门低级语言了,我决定和C一起去。问题是我使用的所有语言都是基于OOP。看作(基于我所做的研究)C没有类或继承。因此,我问你:我应该如何以有组织的方式在O中组织我的代码,而不必切换语言或只是拥有功能无穷无尽的文件?
从未来编辑:这个问题非常愚蠢。我15岁,在我的学校没有CS ......
答案 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更难阅读/维护。