作为一名C ++程序员,我们必须处理概念和相关的关系 在将它们实现到类之前的概念。
但是,如何用C等程序语言设计软件呢? 如果没有C ++中的类的帮助,我怎么能处理概念。
相关:
答案 0 :(得分:31)
如果您熟悉C ++,您可能需要考虑在创建类的任何地方创建数据结构,并创建类似于您通常可能创建的类方法的函数,第一个参数接受指向该结构的指针。
答案 1 :(得分:8)
在面向对象语言中,您习惯先考虑数据对象,然后考虑要将哪些方法或行为应用于这些对象。它有助于程序编程,将您的数据结构与作用于它们的函数分开考虑。
答案 2 :(得分:6)
您可能还会看一下Glib / GObject,它提供了C语言的类机制。它被许多项目使用,它非常强大且经过严格测试。
答案 3 :(得分:6)
答案 4 :(得分:6)
如果您要解决的问题很好地映射到它,则只使用功能分解。
在Objective C和C ++出现之前,记住操作系统,GUI和其他事件驱动的非过程系统都是用C编写的。 C不是Cobol。
在学习C ++之前,我使用函数指针数组在C语言中编写了一个事件驱动的GUI。封装很容易,我没有尝试过多态,一些关系依赖于编码标准和命名约定,因为命名空间和对象不可用。它包含了一个真正的解析器,递归,因为我还没有在Uni上使用Compiler类。是的,它都适合640K,但我确实使用了叠加。
有些人试图使用Structs中的函数指针来拼凑伪对象。我没有看到这一点。在某种程度上,你必须接受你没有使用C ++的事实。
答案 5 :(得分:4)
您已收到很多关于如何在C中实现面向对象概念的建议,但除非问题域使OOP非常受欢迎(例如GUI编程),否则您应该以程序方式使用C和其他过程语言。对于所有情况,OOP都不是IMO本身。
您可能希望查看项目分析/设计阶段的“老旧”structured analysis方法。
答案 6 :(得分:3)
绝对没有什么能阻止你使用你在C ++中使用的所有相同的技术C.面向对象的设计,包括多个继承很简单,实现。您甚至可以通过一点宏观聪明来完成模板编程。唯一的问题是生成的C程序不会像等效的C ++那样优雅,因为该语言对这些概念没有多大帮助。
C ++语言提供的功能实际上只有两个很难解决。首先是C ++为模板专业化提供的帮助。您可能需要比使用C ++更仔细地管理模板对象代码。这是C中模板元编程的一个非常简单的方面,因为让宏做正确的事情是非常棘手的。
更大的问题是,当语言超出范围时,语言不会自动完成类实例,这是一个很大的C ++概念。您必须在C中精心管理资源,其中C ++将在适当的时间自动完成所有工作。
答案 7 :(得分:2)
继续考虑类和类提供的接口。 C ++类将映射到C结构。类成员函数成为常规C函数。提供一个标头,声明“class”的外部接口。接受C ++的某些部分在C - 名称空间,异常(当然还有类)中不可用。
答案 8 :(得分:2)
对于面向对象的语言,例如C ++,问题被分解为对象,顾名思义。使用过程语言,您希望使用功能分解,将问题分解为任务,将每个任务分解为子任务,依此类推......
答案 9 :(得分:2)
在C语言中,程序员通常会通过将相关函数分离为.h / .c文件并将其视为类来模仿类的概念。将变量放在局部范围内可以被认为是“私有的”。
答案 10 :(得分:1)
您可以使用C结构和函数指针模仿C ++类和方法。这有点痛苦(一切都在C ++的幕后完成),但它为你的程序提供了非常好的灵活性。
答案 11 :(得分:1)
好吧,你仍然可以在C中设计漂亮的抽象数据类型。首先是typedef
一个struct,提供create / destroy函数,然后是其他setter / getters / doers来操作该结构:
typedef struct { /* maintain private state here */ unsigned int x; char *y; } mytype_t; /** Creates a new mytype... */ mytype_t *mytype_create(unsigned int x, char *y); /** Destroys a mytype, freeing all associated memory. */ void mytype_destroy(mytype_t *t); /** Does something to mytype... */ void mytype_do_something(mytype_t *t, int bla);
所以你实现了这些函数并通过访问struct中的'private'成员来维护你的状态,它的指针被传递给每个函数。
然后你会像这样使用这个界面:
mytype_t* t = mytype_create(foo, bar); mytype_do_something(t); /* do some other stuff */ mytype_destroy(t);
重点是:只要你输入一个结构,就不允许该类型的用户访问它的成员。他们只应通过为其定义的公共接口/函数与之交谈。
我看到人们为了避免必须在整个地方输入'struct'而对typedefing结构进行修改,但你必须将其视为定义一个新的抽象类型,其内部实现可能会改变。当然,该类型的用户可以潜入并访问成员,但这是一件坏事。 typedef结构意味着“私有,禁止!”。这是隐藏的基本信息。
我倾向于使用前缀命名方式,即mytype_verb
。这有助于智能感知,因为我可以输入mytype_
并获取该类型的函数列表。它还有助于命名冲突,因为C中没有命名空间支持,这就是为什么你会看到大多数C库在他们定义的所有内容之前使用前缀(如sqlite3_
)。
答案 12 :(得分:0)
以下是获取单一继承的方法:
struct Base {
int a;
};
struct MyStruct {
Base parent;
int b;
};
struct MyStruct myStruct;
struct Base *base = (struct Base *) &myStruct;
printf("%d\n", base->a);
aFunctionExpectingBase(base);
这模仿GObject。你可以做他们做的其他技巧,例如:在每个类似对象的结构中,包含一个共同的第一级父级可能很方便。它可以提供C对象系统的基本功能。
答案 13 :(得分:0)
功能分解是一种自上而下的方法,以系统的方式设计程序。我们的想法是将问题分解为子任务,依次分解子任务,直到细节足够精细转换为编程语言。设计师可以选择如何解决问题。