如何用C语言实现C++的多态的编程技巧

2010年01月15日 (16:13)885 views

作者:Pray

分类:编程语言

标签:内存, 动态, 实例, 对象, 指针, 赋值

评论:7 个评论

  我们先用下面的结构来描述一个对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 typedef struct _ClassType 
  { 
  char* name; /*对象名,唯一*/ 
  int object_size;/*对象大小,创建实列时分配内存要用到*/ 
  int class_size; /*全部虚函数大小,如sizeof(CObjectClass)*/ 
  void* vclass; /*虚函数指针*/ 
  void (*InitClassCallback)(void*); /*给对象的虚函数赋值*/ 
  void (*InitObjectCallback)(void*);/*对象实例化时,给实例成员赋初值,有点类似构造函数*/ 
  struct _ClassType* parent; /*父对象*/ 
  struct _ClassType* next; /*单向链表,指向下一对象*/ 
  }ClassType; 
  #define [MAX_CLASS_NUM 128 
  static ClassType classes[MAX_CLASS_NUM]; /*对象池*/ 
  static ClassType *used_classes = NULL; 
  static ClassType *free_classes = NULL;

  这里只定义了128个对象,数目可能修改或者改成动态分配。
  初始化,全部链接到空闲链表中

1
2
3
4
5
6
7
8
9
10
 void InitObjectLib(void) 
  { 
  int i; 
  memset(classes, 0, sizeof(ClassType)*MAX_CLASS_NUM); 
  for( i=0;i  
  { 
  classes[i].next = &(classes[i+1]); 
  } 
  free_classes = &(classes[0]); 
  }

  这个函数既是获取对象的虚函数指针,也是注册对象。
  这里要注意type为static,一个对象只注册一次,下次获取时直接取type。
  RegisterClassType()第一个参数为对象的描述信息,第二个参数为父对象的函数指针,我们来看一下它的定义:

1
2
  #define TOP_OBJECT_TYPE 0 
  #define BASE_OBJECT_TYPE GetObjectType()

  因为CObject为基对象,它没有父对象,所以这里第二个参数为0(TOP_OBJECT_TYPE)。
  现在假设有一个CObject子对象CSubObject,那么注册它时应该这样写:

1
  type = RegisterClassType(&classinfo, BASE_OBJECT_TYPE);

  由此可能看到,这里其实是一个递归:当注册CSubOject里会用到参数BASE_OBJECT_TYPE,既GetObjectType(),这样就可以把CObject也注册上。
  简单的说:如果C继承于B,B继承于A,现在假设A、B还未注册,当注册C时,通过递归也能把B、A注册上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  int GetObjectType(void) 
  { 
  static int type = 0; 
  if( type==0 ) 
  { 
  static ClassInfo classinfo = 
  { 
  "OBJECT", /*对象名,唯一*/ 
  sizeof(CObject), 
  sizeof(CObjectClass), 
  (pInitObjectCallback)InitObject, 
  (pInitClassCallback)InitObjectClass, 
  }; 
  type = RegisterClassType(&classinfo, TOP_OBJECT_TYPE); 
  } 
  return type; 
  }

  我们再来看一看InitObject和InitObjectClass

1
2
3
4
5
6
7
8
9
10
11
12
 static void InitObjectClass(CObjectClass *vclass) 
  { 
  if(vclass==NULL) 
  return; 
  vclass->destory = DestoryObject;/*对虚函数赋值*/ 
  } 
  static void InitObject(CObject *object) 
  { 
  if(object==NULL) 
  return; 
  object->ref_counter = 1; 
  }

  这两个函数在GetObjectType()被传进去,那么又是在哪儿被调用的?
让我们看RegisterClassType()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 int RegisterClassType(ClassInfo *classinfo, int parent_type) 
  { 
  int type = 0; 
  ClassDesc *current, *parent; 
  parent = (ClassType *)parent_type; 
  if( classinfo->name==NULL ) 
  { 
  TRACE("RegisterClassType(): class name is NULL\n"); 
  return type; 
  } 
  /*检查是否有对象名重复*/ 
  current = used_classes; 
  while(current) 
  { 
  if(strcmp(current->name, classinfo->name)==0 ) 
  { 
  TRACE("RegisterClassType(): class name is redefined\n"); 
  unlock(); 
  return type; 
  } 
  current = current->next; 
  } 
  /*创建对象*/ 
  current = free_classes; 
  if(current) 
  { 
  free_classes = free_classes->next; 
  current->name = classinfo->name; 
  current->parent = parent; 
  current->class_size = classinfo->class_size; 
  current->InitClassCallback = classinfo->InitClassCallback; 
  current->InitObjectCallback = classinfo->InitObjectCallback; 
  current->vclass = malloc(current->class_size); 
  if( current->vclass==NULL ) 
  { 
  TRACE("RegisterClassType(): malloc vclass failed\n"); 
  } 
  memset( current->vclass, 0, current->class_size); 
  current->vclass->class_type = (int)current; 
  if( parent )/*子对象的虚函数全部指向父对象的虚函数*/ 
  { 
  memcpy(current->vclass, parent->vclass, parent->class_size); 
  }

  对子对象新添加的虚函数赋值,也可以对继承于父对象的虚函数重赋值。

1
2
  if( current->InitClassCallback ) 
  current->InitClassCallback(current->vclass);

  链接到对象池中

1
2
3
4
5
6
7
8
9
10
 current->next = used_classes; 
  used_classes = current; 
  } 
  else 
  { 
  TRACE("RegisterClassType(): ERROR, no class in class pool\n"); 
  } 
  type = (int)current; 注意:type为ClassType类型的指针。 
  return type; 
  }

  创建对象的实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 CObject *NewObject(void) /*创建一个实例*/ 
  { 
  return NewClassType(BASE_OBJECT_TYPE); 
  } 
  void *NewClassType(int class_type) 
  { 
  ClassType *pclass = NULL; 
  void *object = NULL; 
  if( pclass==0 ) 
  return NULL; 
  pclass = (ClassType*)class_type; 
  /*为实例分配内存空间*/ 
  object = (CObject*)malloc(pclass->object_size); 
  if( object ) 
  { 
  /*实例的虚函数指针指向它的对象的虚函数指针*/ 
  ((CObject*)object)->vclass = pclass->vclass; 
  /*调用父对象的初始化函数,这个函数是递归函数, 
  先初始化基对象,再初始化子对象,再初始化子子对象...*/ 
  InitParentObject(pclass, object); 
  } 
  return object; 
  } 
  static void InitParentObject(ClassType *current, void *object) 
  { 
  if( current ) 
  { 
  if( current->parent ) 
  InitParentObject(current->parent, object); 
  if( current->InitObjectCallback ) 
  current->InitObjectCallback(object); 
  } 
  }

文章地址:http://blog.nodll.com/2010/01/15/about-c-c/Pray.html

上一篇:极光行动:攻击Google的代码曝光
下一篇:胡歌版(神话)全集在线观看

管理日志

  1. 首页
  2. 登录