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

来源:互联网 发布:mysql查看表字段语句 编辑:程序博客网 时间:2024/04/19 23:08

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

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

1. vector 的接口

/********************************************************************created:2013/08/19created:19:8:2013   0:09file base:vectorfile ext:hauthor:Justme0 (http://blog.csdn.net/Justme0)purpose:vector 结构体的定义*********************************************************************/#ifndef _VECTOR_H_#define _VECTOR_H_typedef struct vector vector;typedef charvec_value_type;typedef vec_value_type*vec_pointer;typedef vec_value_type*vec_iterator;typedef unsigned intvec_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/19created:19:8:2013   0:09file base:vectorfile ext:cauthor: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/19created:19:8:2013   0:10file base:testfile ext:cauthor: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\n", *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\n", my_vec.size(&my_vec));printf("back is '%c'\n", 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. 运行结果

ABCDEset [2]: '2'AB2DEnot emptypop_back...AB2Dsize is 4back is 'D'clear...empty请按任意键继续. . .

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

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


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



20140207

今天发现3个 buginsert 拼写错误;insert n 中移动原来数据时将 end - 1 处的元素移动到 end 处(这个 bug 很隐蔽);CHECK_BORDER 宏中将第二个断言改为 end_of_storage >= finish。