zoukankan      html  css  js  c++  java
  • C 语言中实现数据与方法的封装

           在 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 形式”。桑心啊,我只好贴在这独自欣赏了。




  • 相关阅读:
    CSS3—— 2D转换 3D转换 过渡 动画
    CSS3——边框 圆角 背景 渐变 文本效果
    CSS3——表单 计数器 网页布局 应用实例
    CSS3——提示工具 图片廓 图像透明 图像拼接技术 媒体类型 属性选择器
    CSS3——对齐 组合选择符 伪类 伪元素 导航栏 下拉菜单
    CSS3——分组和嵌套 尺寸 display显示 position定位 overflow float浮动
    CSS3——盒子模型 border(边框) 轮廓(outline)属性 margin外边距 padding填充
    Eclipse连接数据库报错Local variable passwd defined in an enclosing scope must be final or effectively final
    数据库——单表查询
    数据库——添加,修改,删除
  • 原文地址:https://www.cnblogs.com/pangblog/p/3268579.html
Copyright © 2011-2022 走看看