现在的位置: 首页 > 综合 > 正文

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

2013年08月07日 ⁄ 综合 ⁄ 共 6669字 ⁄ 字号 评论关闭

       在 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\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. 运行结果

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

抱歉!评论已关闭.