C ++程序员应该如何在C中设计软件?

时间:2009-06-03 18:48:51

标签: c++ c

作为一名C ++程序员,我们必须处理概念和相关的关系 在将它们实现到类之前的概念。

但是,如何用C等程序语言设计软件呢? 如果没有C ++中的类的帮助,我怎么能处理概念。

相关:

14 个答案:

答案 0 :(得分:31)

如果您熟悉C ++,您可能需要考虑在创建类的任何地方创建数据结构,并创建类似于您通常可能创建的类方法的函数,第一个参数接受指向该结构的指针。

答案 1 :(得分:8)

在面向对象语言中,您习惯先考虑数据对象,然后考虑要将哪些方法或行为应用于这些对象。它有助于程序编程,将您的数据结构与作用于它们的函数分开考虑。

答案 2 :(得分:6)

您可能还会看一下Glib / GObject,它提供了C语言的类机制。它被许多项目使用,它非常强大且经过严格测试。

答案 3 :(得分:6)

完全可以将OOP设计原则引入'C'。你错过了一些语法糖,但在一天结束时,它只是结构,函数和指针。

请查看glibgtkgts,了解C中OOP编码风格的好例子。

答案 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)

使用Functional Decomposition

功能分解是一种自上而下的方法,以系统的方式设计程序。我们的想法是将问题分解为子任务,依次分解子任务,直到细节足够精细转换为编程语言。设计师可以选择如何解决问题。