发件人: James C Hu
主题: Re: struct 继承 (C 语言中的 OOP)
日期: Thu, 22 Jan 1998 19:48:56 -0600 (CST)
消息 ID: <slrn6cfto4.ijc.jxh@lambada.cs.wustl.edu>

On Thu, 22 Jan 1998 15:23:25 -0800, Wayne O. Cochran 写道
> 我正在使用 C 编写一些 OOP 代码,并且正在尝试决定
> 实现继承的最佳方式,而不会滥用
> C 标准。 假设我有一个类 POINT(实现为
> 在下面的结构中),我想要另一个类 CIRCLE
> 继承 POINT 的字段,但我希望能够
> 将 CIRCLE 的实例传递给操作
> POINT 实例的函数。 下面的代码取决于
> 结构如何布局它们的字段 -- ANSI C 标准
> 声明字段的地址偏移量按照
> 它们在结构模板中出现的递增顺序排列。
> 这是否滥用 C 标准? 我注意到 X11 Xt
> widget 工具包使用类似的技术在 C 中实现 OOP。
> 顺便说一句,我没有在 FAQ 中找到这个。
>
> typedef struct {
> int x,y;
> } POINT;
>
> typedef struct {
> POINT center;
> int radius;
> } CIRCLE;
>
> void setLocation(POINT *p, int x, int y) {
> p->x = x;
> p->y = y;
> }
>
> CIRCLE c;
> setLocation(&c, 10,15);

除了需要强制类型转换之外,

setLocation((POINT *)&c, 10, 15);

这很好。 ANSI/ISO 9899-1990 6.5.2.1 声明``一个指向结构对象的指针,经过适当的转换,指向它的初始成员''。 因此,在您的情况下,指向 CIRCLE 的指针可以适当地转换为指向 POINT。

最近这个问题越来越普遍。 也许是时候更新 FAQ 了。 欢迎对以下内容提出意见和更正。

问:如何在 C 语言中使用结构实现面向对象 (OO) 的继承?

答:首先,请确保使用面向对象的语言(例如 C++)不是一个好的选择。 C 语言的设计并没有考虑到 OO,因此支持 OO 编程的功能有限。 仔细考虑您将需要哪些 OO 功能,并考虑如何在 C 中实现它们。

也就是说,可以通过在结构内部嵌套结构来在 C 中实现单继承。 这种技术之所以有效,是因为指向结构对象的指针,在经过适当转换后,指向其初始成员。 因此,通过创建一个新的“子”结构来实现“父”结构的单继承,该结构的初始成员与“父”结构的类型相同。 以下示例(感谢 Wayne O. Cochran)说明了如何做到这一点。

typedef struct {
  int x;
  int y;
} point;

typedef struct {
  point center;
  int radius;
} circle;

void init_point(point *p, int x, int y)
{
  p->x = x;
  p->y = y;
}

void init_circle(circle *c, int x, int y, int r)
{
  init_point((void *)c, x, y);
  c->radius = r;
}

在这个例子中,我们看到 `circle' 从 `point' 继承了整数成员 `x' 和 `y'。 请注意,以下函数无效

void bad_init_circle(circle *c, int x, int y, int r)
{
  c->x = x;  /* should be ((point *)c)->x = x; */
  c->y = y;  /* should be ((point *)c)->y = y; */
  c->radius = r;
}

因为指向 circle `c' 的指针尚未适当地转换为指向其第一个成员的类型。

参考文献
ANSI Sec. 3.5.2.1
ISO Sec. 6.5.2.1

--
James C. Hu <jxh@cs.wustl.edu> 计算机科学博士生
http://www.cs.wustl.edu/~jxh/ 圣路易斯华盛顿大学
>>>>>>>>>>>>> 我使用 *SpamBeGone* <URL:http://www.internz.com/SpamBeGone/>