C 言語によるオブジェクト記述法 COOL

http://www.sage-p.com/process/cool.htm

C++ が利用できない環境でオブジェクト指向プログラミングを行う方法です。とりあえず可変長配列を実装してみます。多少冗長な感じですが、慣れれば組み込み系の大規模開発などでは、特に重宝すると思います。

いきなり書き始めるよりは、this ポインターを省略せずに書いた C++ のクラスをそのまま移植するのが楽かもしれません(例ではそうやってます)。

object.h

#ifndef __OBJECT_H__
#define __OBJECT_H__

extern "C" {
	typedef struct Object {
		int id;
	};
	Object* Object_new();
	void Object_setId(Object* self, int id);
	void Object_delete(Object* self);
}

#endif

object.cpp

#include <stdio.h>
#include <stdlib.h>
#include "object.h"

Object* Object_new()
{
	Object* self = (Object *) malloc(sizeof(Object));
	self->id = 0;
	return self;
}

void Object_setId(Object* self, int id)
{
	self->id = id;
}

void Object_delete(Object* self)
{
	free(self);
}

vector.h

#ifndef __VECTOR_H__
#define __VECTOR_H__

extern "C" {
	typedef struct Vector {
		Object** _elements;
		int _size;
		int _capacity;
	};
	#define Vector_defaultCapacity 2
	Vector* Vector_new();
	void Vector_initialize(Vector* self);
	void Vector_delete(Vector* self);
	void Vector_add(Vector* self, Object* item);
	Object* Vector_removeAt(Vector* self, int index);
	Object* Vector_get(Vector* self, int index);
	int Vector_size(Vector* self);
}

#endif

vector.cpp

#include <stdio.h>
#include <stdlib.h>
#include "object.h"
#include "vector.h"

Vector* Vector_new()
{
	Vector* self = (Vector *) malloc(sizeof(Vector));
	Vector_initialize(self);
	return self;
}

void Vector_initialize(Vector* self)
{
	self->_elements = (Object **) malloc(sizeof(Vector) * Vector_defaultCapacity);
	self->_size = 0;
	self->_capacity = Vector_defaultCapacity;
}

void Vector_delete(Vector* self)
{
	delete [] self->_elements;
}

void Vector_add(Vector* self, Object* item)
{
	if (self->_size == self->_capacity) {
		/* 足りなくなったら容量を倍に増やす */
		self->_capacity <<= 1;
		Object** ptr = (Object **) malloc(sizeof(Vector) * self->_capacity);
		for (int i = 0; i < self->_size; i++) ptr[i] = self->_elements[i];
		delete [] self->_elements;
		self->_elements = ptr;
	}
	self->_elements[self->_size] = item;
	self->_size++;
}

Object* Vector_removeAt(Vector* self, int index)
{
	if (index < 0) return NULL;
	self->_size--;
	Object* obj = self->_elements[index];
	for (int i = index; i < self->_size; i++) {
		self->_elements[i] = self->_elements[i + 1];
	}
	return obj;
}

Object* Vector_get(Vector* self, int index)
{
	return (index < 0) ? NULL : self->_elements[index];
}

int Vector_size(Vector* self)
{
	return self->_size;
}

main.cpp

#include <stdio.h>
#include <stdlib.h>
#include "object.h"
#include "vector.h"

int main(void)
{
	Vector* vector = Vector_new();
	for (int i = 0; i < 4; i++) {
		Object* obj = Object_new();
		Object_setId(obj, i);
		Vector_add(vector, obj);
	}
	for (int i = 0; i < 4; i++) {
		Object* obj = Vector_removeAt(vector, 0);
		printf("vector size = %d, object id = %d\n", Vector_size(vector), obj->id);
		Object_delete(obj);
	}
	Vector_delete(vector);
	
	return 0;
}

実行結果

vector size = 3, object id = 0
vector size = 2, object id = 1
vector size = 1, object id = 2
vector size = 0, object id = 3