C 语言中实现数据与方法的封装

在 C 语言中可以用结构体代替类,用函数指针代替成员方法,实现数据成员与成员方法的封装,在客户端写出的程序与 C++ 类似,唯一的不同是 C 语言中调用函数指针成员时必须将本对象的地址传给函数,因为 C 语言中各函数的地位是相同的。

本文以模仿 STL 中的 vector 类写了一个 C 语言的 vector 结构体,程序如下:

1. vector 的接口

 

[cpp][/cpp] view plaincopyprint?

  1. /********************************************************************
  2.     created:    2013/08/19
  3.     created:    19:8:2013   0:09
  4.     file base:  vector
  5.     file ext:   h
  6.     author:     Justme0 (http://blog.csdn.net/Justme0)
  7.     purpose:    vector 结构体的定义
  8. *********************************************************************/
  9. #ifndef _VECTOR_H_
  10. #define _VECTOR_H_
  11. typedef struct vector vector;
  12. typedef char            vec_value_type;
  13. typedef vec_value_type* vec_pointer;
  14. typedef vec_value_type* vec_iterator;
  15. typedef unsigned int    vec_size_type;
  16. struct vector {
  17.     /*
  18.     ** 获取下标为 index 的元素
  19.     */
  20.     vec_value_type (*get_at)(vector *pvec, const int index);
  21.     /*
  22.     ** 设置下标为 index 处的元素为 elem
  23.     */
  24.     void (*set_at)(vector *pvec, const int index, const vec_value_type elem);
  25.     vec_iterator (*begin)(vector *pvec);
  26.     vec_iterator (*end)(vector *pvec);
  27.     vec_value_type (*front)(vector *pvec);
  28.     vec_value_type (*back)(vector *pvec);
  29.     int (*size)(vector *pvec);
  30.     int (*capacity)(vector *pvec);
  31.     int (*empty)(vector *pvec);
  32.     void (*insert_n)(vector *pvec, const vec_iterator position, const vec_size_type n, const vec_value_type elem);
  33.     vec_iterator (*earse_pos)(vector *pvec, const vec_iterator position);
  34.     vec_iterator (*earse_int)(vector *pvec, const vec_iterator first, const vec_iterator last);
  35.     void (*clear)(vector *pvec);
  36.     void (*push_back)(vector *pvec, const vec_value_type elem);
  37.     void (*pop_back)(vector *pvec);
  38.     vec_iterator _start;
  39.     vec_iterator _finish;
  40.     vec_iterator _end_of_storage;
  41. };
  42. void vec_construct(vector *pvec);
  43. void vec_construct_n(vector *pvec, const int size);
  44. void vec_destruct(vector *pvec);
  45. #endif

2. vector 的实现

 

 

[cpp][/cpp] view plaincopyprint?

  1. /********************************************************************
  2.     created:    2013/08/19
  3.     created:    19:8:2013   0:09
  4.     file base:  vector
  5.     file ext:   c
  6.     author:     Justme0 (http://blog.csdn.net/Justme0)
  7.     purpose:    vector 的实现
  8. *********************************************************************/
  9. #include “vector.h”
  10. #include <math.h>
  11. #include <stdlib.h>
  12. #include <assert.h>
  13. #define CHECK_BORDER assert(pvec->_finish >= pvec->_start && pvec->_end_of_storage >= pvec->_start)
  14. static vec_iterator copy(vec_iterator first, vec_iterator last, vec_iterator result) {
  15.     vec_iterator src = first;
  16.     vec_iterator dst = result;
  17.     for (; src != last; ++src, ++dst) {
  18.         *dst = *src;
  19.     }
  20.     return dst;
  21. }
  22. static vec_value_type _get_at(vector *pvec, int index) {
  23.     return *(pvec->begin(pvec) + index);
  24. }
  25. static void _set_at(vector *pvec, int index, vec_value_type elem) {
  26.     pvec->_start[index] = elem;
  27. }
  28. static vec_iterator _begin(vector *pvec) {
  29.     return pvec->_start;
  30. }
  31. static vec_iterator _end(vector *pvec) {
  32.     return pvec->_finish;
  33. }
  34. static vec_value_type _front(vector *pvec) {
  35.     return *pvec->begin(pvec);
  36. }
  37. static vec_value_type _back(vector *pvec) {
  38.     return *(pvec->end(pvec) – 1);
  39. }
  40. static int _size(vector *pvec) {
  41.     return pvec->end(pvec) – pvec->begin(pvec);
  42. }
  43. static int _capacity(vector *pvec) {
  44.     return pvec->_end_of_storage – pvec->begin(pvec);
  45. }
  46. static int _empty(vector *pvec) {
  47.     return pvec->begin(pvec) == pvec->end(pvec);
  48. }
  49. static void _insert_n(vector *pvec, vec_iterator position, vec_size_type n, const vec_value_type elem) {
  50.     vec_size_type old_size = 0;
  51.     vec_size_type new_size = 0;
  52.     int inset_index = 0;
  53.     vec_iterator ite = NULL;
  54.     assert(pvec->_start <= position && position <= pvec->end(pvec));
  55.     CHECK_BORDER;
  56.     if (0 == n) {
  57.         return ;
  58.     }
  59.     inset_index = position – pvec->_start;
  60.     old_size = pvec->size(pvec);
  61.     new_size = old_size + n;
  62.     // 先检查剩余空间是否足够,不够则扩容
  63.     if ((vec_size_type)(pvec->_end_of_storage – pvec->_finish) < n) {
  64.         const vec_size_type new_capacity = old_size + __max(old_size, n);
  65.         vec_value_type *new_base = (vec_value_type *)realloc(pvec->_start, new_capacity * sizeof(vec_value_type));
  66.         if (NULL == new_base) {
  67.             exit(OVERFLOW); // 此时原来的空间将发生内存泄漏
  68.         }
  69.         pvec->_start = new_base;
  70.         pvec->_end_of_storage = pvec->_start + new_capacity;
  71.     }
  72.     pvec->_finish = pvec->_start + new_size;
  73.     position = pvec->_start + inset_index;
  74.     // 移动元素
  75.     for (ite = pvec->_finish; ite >= position + n; –ite) {
  76.         *ite = *(ite – n);
  77.     }
  78.     // 插入n个新元素
  79.     for (; ite >= position; –ite) {
  80.         *ite = elem;
  81.     }
  82. }
  83. static vec_iterator _earse_pos(vector *pvec, const vec_iterator position) {
  84.     if (position + 1 != pvec->end(pvec)) {
  85.         copy(position + 1, pvec->_finish, position);
  86.     }
  87.     –pvec->_finish;
  88.     return position;
  89. }
  90. static vec_iterator _earse_int(vector *pvec, const vec_iterator first, const vec_iterator last) {
  91.     vec_iterator i = copy(last, pvec->_finish, first);
  92.     pvec->_finish -= last – first;
  93.     return first;
  94. }
  95. static void _clear(vector *pvec) {
  96.     pvec->earse_int(pvec, pvec->begin(pvec), pvec->end(pvec));
  97. }
  98. static void _push_back(vector *pvec, const vec_value_type elem) {
  99.     CHECK_BORDER;
  100.     _insert_n(pvec, pvec->end(pvec), 1, elem);
  101. }
  102. static void _pop_back(vector *pvec) {
  103.     pvec->earse_pos(pvec, pvec->end(pvec) – 1);
  104. }
  105. static void set(vector *pvec) {
  106.     pvec->_finish = NULL;
  107.     pvec->_start = NULL;
  108.     pvec->_end_of_storage = NULL;
  109.     pvec->get_at = _get_at;
  110.     pvec->set_at = _set_at;
  111.     pvec->begin = _begin;
  112.     pvec->end = _end;
  113.     pvec->front = _front;
  114.     pvec->back = _back;
  115.     pvec->size = _size;
  116.     pvec->capacity = _capacity;
  117.     pvec->empty = _empty;
  118.     pvec->insert_n = _insert_n;
  119.     pvec->earse_pos = _earse_pos;
  120.     pvec->earse_int = _earse_int;
  121.     pvec->clear = _clear;
  122.     pvec->push_back = _push_back;
  123.     pvec->pop_back = _pop_back;
  124. }
  125. static void reset(vector *pvec) {
  126.     pvec->_finish = NULL;
  127.     pvec->_start = NULL;
  128.     pvec->_end_of_storage = NULL;
  129.     pvec->get_at = NULL;
  130.     pvec->set_at = NULL;
  131.     pvec->begin = NULL;
  132.     pvec->end = NULL;
  133.     pvec->front = NULL;
  134.     pvec->back = NULL;
  135.     pvec->size = NULL;
  136.     pvec->capacity = NULL;
  137.     pvec->empty = NULL;
  138.     pvec->insert_n = NULL;
  139.     pvec->earse_pos = NULL;
  140.     pvec->earse_int = NULL;
  141.     pvec->clear = NULL;
  142.     pvec->push_back = NULL;
  143.     pvec->pop_back = NULL;
  144. }
  145. void vec_construct(vector *pvec) {
  146.     set(pvec);
  147. }
  148. void vec_construct_n(vector *pvec, const int size) {
  149.     set(pvec);
  150.     pvec->_start = (vec_iterator)malloc(size * sizeof(*pvec->_start));
  151.     if (NULL == pvec->_start) {
  152.         // TODO:
  153.         exit(OVERFLOW);
  154.     }
  155.     pvec->_finish = pvec->_start + size;
  156.     pvec->_end_of_storage = pvec->_finish;
  157. }
  158. void vec_destruct(vector *pvec) {
  159.     free(pvec->_start);
  160.     reset(pvec);
  161. }

3. 测试程序

 

 

[cpp][/cpp] view plaincopyprint?

  1. /********************************************************************
  2.     created:    2013/08/19
  3.     created:    19:8:2013   0:10
  4.     file base:  test
  5.     file ext:   c
  6.     author:     Justme0 (http://blog.csdn.net/Justme0)
  7.     purpose:    vector 的测试程序
  8. *********************************************************************/
  9. #include “vector.h”
  10. #include <stdio.h>
  11. void output(vector *pvec) {
  12.     vec_iterator iter;
  13.     for (iter = pvec->begin(pvec); iter != pvec->end(pvec); ++iter) {
  14.         printf(“%c\n”, *iter);
  15.     }
  16. }
  17. int main(int argc, char **argv) {
  18.     char ch = ‘A’;
  19.     int cnt = 5;
  20.     vector my_vec;
  21.     vec_construct(&my_vec);
  22.     while (cnt–) {
  23.         my_vec.push_back(&my_vec, ch++);
  24.     }
  25.     output(&my_vec);
  26.     puts(“set [2]: ‘2’”);
  27.     my_vec.set_at(&my_vec, 2, ‘2’);
  28.     output(&my_vec);
  29.     my_vec.empty(&my_vec) ? puts(“empty”) : puts(“not empty”);
  30.     puts(“pop_back…”);
  31.     my_vec.pop_back(&my_vec);
  32.     output(&my_vec);
  33.     printf(“size is %d\n”, my_vec.size(&my_vec));
  34.     printf(“back is ‘%c’\n”, my_vec.back(&my_vec));
  35.     puts(“clear…”);
  36.     my_vec.clear(&my_vec);
  37.     my_vec.empty(&my_vec) ? puts(“empty”) : puts(“not empty”);
  38.     vec_destruct(&my_vec);
  39.     return 0;
  40. }

4. 运行结果

 

 

[plain][/plain] view plaincopyprint?

  1. A
  2. B
  3. C
  4. D
  5. E
  6. set [2]: ‘2’
  7. A
  8. B
  9. 2
  10. D
  11. E
  12. not empty
  13. pop_back…
  14. A
  15. B
  16. 2
  17. D
  18. size is 4
  19. back is ‘D’
  20. clear…
  21. empty
  22. 请按任意键继续. . .

1、在测试程序中可以看到,定义一个结构体后,必须紧跟着用函数 construct 将对象的成员赋值以初始化,我称这个过程为“构造”。

 

2、最后必须显示调用 destruct 函数将对象“析构”,释放对象 malloc 的空间。

 

我将这个程序给某个 C++ 游戏程序员看,被他一阵批,说我的程序最大的缺点就是 不是面向对象;没有一个企业会让这份程序通过;“你写的是 Objective-C 形式”。桑心啊,我只好贴在这独自欣赏了。

标签