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




  • 相关阅读:
    [Effective C++ --009]确定对象被使用前已先被初始化
    [Effective C++ --008]别让异常逃离析构函数
    [Effective C++ --007]为多态基类声明virtual析构函数
    [Effective C++ --006]若不能使用编译器自动生成的函数,就该明确拒绝
    [Effective C++ --005]了解C++默默编写并调用哪些函数
    [000]socket通信--server和client实现的简单例子
    [014]模板-模板实参推导
    [013]模板-非类型模板参数
    [012]泛型--lambda表达式捕获
    U3d keyCode值对应的按键
  • 原文地址:https://www.cnblogs.com/pangblog/p/3268579.html
Copyright © 2011-2022 走看看