Drobne programowanie

Kaczuś zaprasza do opowieści o algorytmach, językach programowania i strukturach danych

Na stronie stosowane są pliki cookies. Więcej na podstronie.
odsłon: 1934

Programowanie obiektowe w C część 1

Wstęp

Zdarza się nam, że mamy do napisania jakiś program, a niestety często wybór języka z różnych przyczyn jest dość ograniczony. Należy pamiętać jednak, że to nie język jest najistotniejszy (choć potrafi na pewno pomóc), a to jak w nim napiszemy program. Istotne jest, aby raz napisany kod można było wykorzystać w innych projektach. Wspaniale by było, gdyby po pewnym czasie dało się układać programy jak z klocków, dopisując jedynie pewne fragmenty wyróżniające nowy projekt.
Przyjrzyjmy się zatem programowaniu obiektowemu. Okazuje się, że jak najbardziej spełnia to zadanie, dając jednocześnie dodatkowe bonusy dla programisty. Dlatego wiele osób wybiera języki wspierające programowanie obiektowe. Jednak, jak pokazuje życie, obiektowo można programować w zasadzie w każdym języku (w tych wspierających jest to po prostu łatwiejsze).
Co zrobić, gdy język nie wspiera za bardzo programowania obiektowego. Czasem muszę napisać coś w języku C. Dzięki odpowiedniemu zaprojektowaniu interfejsu okazuje się, że da się skorzystać z wielu zalet programowania obiektowego.

Projekt obiektu podstawowego

W pierwszej części proponuję zaprojektować obiekt podstawowy, który będzie rodzicem dla innych obiektów. Doświadczenie podpowiada, że przydadzą się konstruktor domyślny, konstruktor kopiujący, destruktor oraz metoda mówiąca o rozmiarze obiektu.
Tak więc będą nam potrzebne definicje typów metod:
typedef void (*ObjectDefaultDestructor)(struct TDefaultObj *);
typedef size_t (*ObjectDefaultGetSize)(struct TDefaultObj *);
typedef struct TDefaultObj * (*ObjectDefaultClone)(struct TDefaultObj *);
główna struktura zyska postać:
struct TDefaultObj
{
	ObjectDefaultDestructor fooDestructor; 
	ObjectDefaultGetSize fooGetSize;
	ObjectDefaultClone fooCloneObj;
};
oraz zadeklarujmy domyślne metody:
struct TDefaultObj *CloneDefaultObject(struct TDefaultObj *asrc);
void FreeDefaultObject(struct TDefaultObj *aobj);
Proponuję, aby definicje tych metod wyglądały następująco:
struct TDefaultObj *CloneDefaultObject(struct TDefaultObj *asrc)
{
	struct TDefaultObj *lres = NULL;
	size_t x;
	if (asrc)
	{
		if (asrc->fooCloneObj != NULL)
			lres = asrc->fooCloneObj(asrc);
		else if(asrc->fooGetSize != NULL)
		{
			x = asrc->fooGetSize(asrc);
			lres = malloc(x);
			memcpy(lres, asrc, x);
		}
	}
	
	return lres;
}

void FreeDefaultObject(struct TDefaultObj *aobj)
{
	if (asrc)
	{
		if (asrc->fooDestructor == NULL)
		{
			free(asrc);
		}
		else
			asrc->fooDestructor(asrc);
	}
}

Przyjęliśmy kilka założeń:
  • domyślny alokator/dealokator to odpowiednio malloc/free.
  • domyślny konstruktor kopiujący albo wywołuje konstruktor obiektu kopiowanego (jeśli jest zdefiniowany), albo wykorzystuje metodę informującą o rozmiarze obiektu. Brak jednej z tych metod spowoduje niedziałanie konstruktora kopiującego
Przyklad wykorzystania znajdziecie Państwo w kolejnym odcinku, do którego zapraszam.
Tomasz Kaczanowski

2013-08-01 21:35:00


C obiektowo C programowanie obiektowe programowanie obiekt podstawowy Cykl język C