在 C 语言中可以用结构体代替类,用函数指针代替成员方法,实现数据成员与成员方法的封装,在客户端写出的程序与 C++ 类似,唯一的不同是 C 语言中调用函数指针成员时必须将本对象的地址传给函数,因为 C 语言中各函数的地位是相同的。
本文以模仿 STL 中的 vector 类写了一个 C 语言的 vector 结构体,程序如下:
1. vector 的接口
/******************************************************************** created: 2013/08/19 created: 19:8:2013 0:09 file base: vector file ext: h author: Justme0 (http://blog.csdn.net/Justme0) purpose: vector 结构体的定义 *********************************************************************/ #ifndef _VECTOR_H_ #define _VECTOR_H_ typedef struct vector vector; typedef char vec_value_type; typedef vec_value_type* vec_pointer; typedef vec_value_type* vec_iterator; typedef unsigned int vec_size_type; struct vector { /* ** 获取下标为 index 的元素 */ vec_value_type (*get_at)(vector *pvec, const int index); /* ** 设置下标为 index 处的元素为 elem */ void (*set_at)(vector *pvec, const int index, const vec_value_type elem); vec_iterator (*begin)(vector *pvec); vec_iterator (*end)(vector *pvec); vec_value_type (*front)(vector *pvec); vec_value_type (*back)(vector *pvec); int (*size)(vector *pvec); int (*capacity)(vector *pvec); int (*empty)(vector *pvec); void (*insert_n)(vector *pvec, const vec_iterator position, const vec_size_type n, const vec_value_type elem); vec_iterator (*earse_pos)(vector *pvec, const vec_iterator position); vec_iterator (*earse_int)(vector *pvec, const vec_iterator first, const vec_iterator last); void (*clear)(vector *pvec); void (*push_back)(vector *pvec, const vec_value_type elem); void (*pop_back)(vector *pvec); vec_iterator _start; vec_iterator _finish; vec_iterator _end_of_storage; }; void vec_construct(vector *pvec); void vec_construct_n(vector *pvec, const int size); void vec_destruct(vector *pvec); #endif
2. vector 的实现
/******************************************************************** created: 2013/08/19 created: 19:8:2013 0:09 file base: vector file ext: c author: Justme0 (http://blog.csdn.net/Justme0) purpose: vector 的实现 *********************************************************************/ #include "vector.h" #include <math.h> #include <stdlib.h> #include <assert.h> #define CHECK_BORDER assert(pvec->_finish >= pvec->_start && pvec->_end_of_storage >= pvec->_start) static vec_iterator copy(vec_iterator first, vec_iterator last, vec_iterator result) { vec_iterator src = first; vec_iterator dst = result; for (; src != last; ++src, ++dst) { *dst = *src; } return dst; } static vec_value_type _get_at(vector *pvec, int index) { return *(pvec->begin(pvec) + index); } static void _set_at(vector *pvec, int index, vec_value_type elem) { pvec->_start[index] = elem; } static vec_iterator _begin(vector *pvec) { return pvec->_start; } static vec_iterator _end(vector *pvec) { return pvec->_finish; } static vec_value_type _front(vector *pvec) { return *pvec->begin(pvec); } static vec_value_type _back(vector *pvec) { return *(pvec->end(pvec) - 1); } static int _size(vector *pvec) { return pvec->end(pvec) - pvec->begin(pvec); } static int _capacity(vector *pvec) { return pvec->_end_of_storage - pvec->begin(pvec); } static int _empty(vector *pvec) { return pvec->begin(pvec) == pvec->end(pvec); } static void _insert_n(vector *pvec, vec_iterator position, vec_size_type n, const vec_value_type elem) { vec_size_type old_size = 0; vec_size_type new_size = 0; int inset_index = 0; vec_iterator ite = NULL; assert(pvec->_start <= position && position <= pvec->end(pvec)); CHECK_BORDER; if (0 == n) { return ; } inset_index = position - pvec->_start; old_size = pvec->size(pvec); new_size = old_size + n; // 先检查剩余空间是否足够,不够则扩容 if ((vec_size_type)(pvec->_end_of_storage - pvec->_finish) < n) { const vec_size_type new_capacity = old_size + __max(old_size, n); vec_value_type *new_base = (vec_value_type *)realloc(pvec->_start, new_capacity * sizeof(vec_value_type)); if (NULL == new_base) { exit(OVERFLOW); // 此时原来的空间将发生内存泄漏 } pvec->_start = new_base; pvec->_end_of_storage = pvec->_start + new_capacity; } pvec->_finish = pvec->_start + new_size; position = pvec->_start + inset_index; // 移动元素 for (ite = pvec->_finish; ite >= position + n; --ite) { *ite = *(ite - n); } // 插入n个新元素 for (; ite >= position; --ite) { *ite = elem; } } static vec_iterator _earse_pos(vector *pvec, const vec_iterator position) { if (position + 1 != pvec->end(pvec)) { copy(position + 1, pvec->_finish, position); } --pvec->_finish; return position; } static vec_iterator _earse_int(vector *pvec, const vec_iterator first, const vec_iterator last) { vec_iterator i = copy(last, pvec->_finish, first); pvec->_finish -= last - first; return first; } static void _clear(vector *pvec) { pvec->earse_int(pvec, pvec->begin(pvec), pvec->end(pvec)); } static void _push_back(vector *pvec, const vec_value_type elem) { CHECK_BORDER; _insert_n(pvec, pvec->end(pvec), 1, elem); } static void _pop_back(vector *pvec) { pvec->earse_pos(pvec, pvec->end(pvec) - 1); } static void set(vector *pvec) { pvec->_finish = NULL; pvec->_start = NULL; pvec->_end_of_storage = NULL; pvec->get_at = _get_at; pvec->set_at = _set_at; pvec->begin = _begin; pvec->end = _end; pvec->front = _front; pvec->back = _back; pvec->size = _size; pvec->capacity = _capacity; pvec->empty = _empty; pvec->insert_n = _insert_n; pvec->earse_pos = _earse_pos; pvec->earse_int = _earse_int; pvec->clear = _clear; pvec->push_back = _push_back; pvec->pop_back = _pop_back; } static void reset(vector *pvec) { pvec->_finish = NULL; pvec->_start = NULL; pvec->_end_of_storage = NULL; pvec->get_at = NULL; pvec->set_at = NULL; pvec->begin = NULL; pvec->end = NULL; pvec->front = NULL; pvec->back = NULL; pvec->size = NULL; pvec->capacity = NULL; pvec->empty = NULL; pvec->insert_n = NULL; pvec->earse_pos = NULL; pvec->earse_int = NULL; pvec->clear = NULL; pvec->push_back = NULL; pvec->pop_back = NULL; } void vec_construct(vector *pvec) { set(pvec); } void vec_construct_n(vector *pvec, const int size) { set(pvec); pvec->_start = (vec_iterator)malloc(size * sizeof(*pvec->_start)); if (NULL == pvec->_start) { // TODO: exit(OVERFLOW); } pvec->_finish = pvec->_start + size; pvec->_end_of_storage = pvec->_finish; } void vec_destruct(vector *pvec) { free(pvec->_start); reset(pvec); }
3. 测试程序
/******************************************************************** created: 2013/08/19 created: 19:8:2013 0:10 file base: test file ext: c author: Justme0 (http://blog.csdn.net/Justme0) purpose: vector 的测试程序 *********************************************************************/ #include "vector.h" #include <stdio.h> void output(vector *pvec) { vec_iterator iter; for (iter = pvec->begin(pvec); iter != pvec->end(pvec); ++iter) { printf("%c ", *iter); } } int main(int argc, char **argv) { char ch = 'A'; int cnt = 5; vector my_vec; vec_construct(&my_vec); while (cnt--) { my_vec.push_back(&my_vec, ch++); } output(&my_vec); puts("set [2]: '2'"); my_vec.set_at(&my_vec, 2, '2'); output(&my_vec); my_vec.empty(&my_vec) ? puts("empty") : puts("not empty"); puts("pop_back..."); my_vec.pop_back(&my_vec); output(&my_vec); printf("size is %d ", my_vec.size(&my_vec)); printf("back is '%c' ", my_vec.back(&my_vec)); puts("clear..."); my_vec.clear(&my_vec); my_vec.empty(&my_vec) ? puts("empty") : puts("not empty"); vec_destruct(&my_vec); return 0; }
4. 运行结果
A B C D E set [2]: '2' A B 2 D E not empty pop_back... A B 2 D size is 4 back is 'D' clear... empty 请按任意键继续. . .
1、在测试程序中可以看到,定义一个结构体后,必须紧跟着用函数 construct 将对象的成员赋值以初始化,我称这个过程为“构造”。
2、最后必须显示调用 destruct 函数将对象“析构”,释放对象 malloc 的空间。
我将这个程序给某个 C++ 游戏程序员看,被他一阵批,说我的程序最大的缺点就是 不是面向对象;没有一个企业会让这份程序通过;“你写的是 Objective-C 形式”。桑心啊,我只好贴在这独自欣赏了。