Inside Object-Oriented Programming Using ANSI C
系列之二
一、 C 的继承。
/* flower.h */
#ifndef _FLOWER_H
#define _FLOWER_H
typedef struct _tag_Flower Flower;
struct _tag_Flower
{
int color;
};
#endif
|
/* flower.c */
#include <stdio.h>
#include <assert.h>
#include "flower.h"
void
flower_set_color(Flower* self, int color)
{
assert(self != NULL);
self->color = color;
}
int
flower_get_color(Flower* self)
{
assert(self != NULL);
return self->color;
}
void
flower_blow(Flower* self)
{
printf("listen, the flower's blowing voice ... \n");
}
|
现在,Rose 将继承自 Flower :
/* rose.h */
#ifndef _ROSE_H
#define _ROSE_H
#include "flower.h"
typedef struct _tag_Rose Rose;
struct _tag_Rose
{
Flower flower; /* must be first */
/* private */
int thorn;
};
#endif
|
/* rose.c */
#include <stdio.h>
#include <assert.h>
#include "rose.h"
void
rose_set_thorn_nr(Rose* self, int thorn)
{
assert(self != NULL);
self->thorn = thorn;
}
int
rose_get_thorn_nr(Rose* self)
{
assert(self != NULL);
return self->thorn;
}
void
rose_blow(Rose* self)
{
printf("listen, rose is blowing, and your lover is coming ... \n");
}
|
相应的测试程序如下:
/* demo.c */
#include <stdio.h>
#include <assert.h>
#include "rose.h"
int
main(int argc, char* argv[])
{
Rose rose;
Flower* flower = (Flower*) &rose;
flower_set_color(flower, 255);
printf("rose color :%d\n", rose.flower.color);
printf("rose color: %d\n", flower_get_color(flower));
rose_set_thorn_nr(&rose, 11);
printf("rose has %d thorns.\n", rose_get_thorn_nr(&rose));
printf("flower blow:\n");
flower_blow(flower);
printf("rose blow:\n");
rose_blow(&rose);
return 0;
}
|
在命令行编译:
$ gcc -o demo demo.c rose.c flower.c
运行:
$ ./demo
你可以看见输出的结果。可以体会一下。这里想强调的是在 struct Rose 的定义的时候,第一个元素必须是 Flower, 这样确保强制转换后正好和 Flower 相对应,这正是在开篇提到的 C 语言的特性所致。
二、 动态链接
动态链接以在运行时确定加载的模块,绝大多数流行的基于插件的项目都是以这种机制来实现的。
函数指针在这里扮演非常重要的角色。
/* test.c */
#include <stdio.h>
int
func_add(int a, int b)
{
return (a + b);
}
int
func_multi(int a, int b)
{
return (a * b);
}
int
main(int argc, char* argv[])
{
int result = 0;
if (argc != 3)
goto usage;
if (0 == strcmp("static", argv[1]))
{
if (argv[2][0] == '+')
result = func_add(11, 22);
else if (argv[2][0] == '*' )
result = func_multi(11, 22);
else
goto usage;
}
else if (0 == strcmp("dynamic", argv[1]))
{
typedef int (*func)(int, int );
func func_pointer;
if ('+' == argv[2][0])
func_pointer = func_add;
else if ('*' == argv[2][0])
func_pointer = func_multi;
else
goto usage;
result = func_pointer(11, 22);
}
else
goto usage;
printf("result: \n", result);
return 0;
usage:
printf("usage: test [static|dynamic] [+|*]\n");
return 1;
}
|
$ gcc -o test test.c
注意:测试乘法运算函数时,需要将 * 号转义。
$ ./test dynamic \*
动态链接让子类覆盖父类的同名函数成为可能。这将在后续的章节中详细讨论。
阅读(1477) | 评论(0) | 转发(0) |