Posts‎ > ‎

C with Pseudo-Classes

posted 8 Jul 2011, 13:06 by Rodrigo Caetano Rocha   [ updated 9 Jul 2011, 20:26 ]
   Despite the fact that C is a programming language developed in the 70's it is still widely used. It might happen that we have only a C compiler available in the enviroment that is being used. Even if it is not the case, suppose we need to develop an application using just C. 
   We know that Object-Oriented Programming have many advantages over conventional approaches, some of the advantages are:
   - OOP provides a clear modular structure for programs which makes it good for defining abstract data-types where implementation details are hidden and the unit has a clearly defined interface.
   - OOP makes it easy to maintain and modify existing code as new objects can be created with small differences to existing ones.
   - OOP provides a good framework for code libraries where supplied software components can be easily adapted and modified by the programmer.

   OOP has some concepts such as Objects, Classes, Data Abstraction and Encapsulation, Inheritance and Polymorphism.

   In this post I will show how to use C with Pseudo-Classes.
   The basic idea used to create a pseudo-class in C is to use structures (struct) and function pointers.
   To ease this task I've created some macro definitions.

/* file: cclass.h */
#ifndef _CCLASS
#define _CCLASS

#include <stdlib.h>
#include <assert.h>

#define NEW(_CLASS_) ((_CLASS_*)malloc(sizeof(_CLASS_)))
#define DELETE(_OBJ_) free(_OBJ_)
#define FUNC(_TYPE_, _NAME_, _PARAM_) _TYPE_ (*_NAME_)_PARAM_
#define CLASS( _NAME_, _BODY_ ) typedef struct _NAME_ { _BODY_ } _NAME_

#endif
   
   - NEW is just a macro that call the malloc function to dynamically allocate a memory area for an object of a given class.
   - DELETE calls the free function to deallocate the memory area of an object.
   - FUNC is a macro for letting the function pointers, that will represent the methods of the classes, a bit more readable.
   - CLASS is the macro to create pseudo-classes.
   Now that we have some macros, we will make use of them to create our pseudo-classes.

   The two following files shows how to create a simple class. It is very similar to C++.

/* file: node.h */
#ifndef _NODE
#define _NODE
#include "cclass.h"

CLASS( node, 
   int val;
   
   FUNC( int, get, (struct node *) );
   FUNC( void, set, (struct node *, int) );
);

node *new_node(int v);
void del_node(node *n);

#endif

   Note that the FUNC macro receives three arguments, the first is the return-type of the function, the second is the name of the function and the third is the formal parameter list within brackets. CLASS receives two arguments, the first is the name of the class and the second is the declarations of the class. A detail very important is that every function declared in the class MUST receive an "object" of itself, that will be used as the "this" in C++.

/* file: node.c */
#include "node.h"

static int get(node *this)
{
   return  this->val;
}

static void set(node *this, int v)
{
   this->val = v;
}

node *new_node(int v)
{
   node *n = NEW(node);
   assert(n);

   n->set = set;
   n->get = get;

   n->val = v;

   return n;
}

void del_node(node *n)
{
   DELETE(n);
}

   Note that the functions get and set are static in this file, it is useful for keeping them visible only in this file. The new_node function is the constructor of the class node. It allocates a memory area for the object of the class and bind the function pointers to its function. The constructor is also responsible for initialising some attributes of the class and returning the new object of the class.
   The del_node is the destructor function of the class node, it just deallocates the memory area.

   The following file is an example of how to use the class that we have done.

/* file: main.c */
#include <stdio.h>
#include "node.h"

main()
{
   node *n = new_node(7);

   printf("%d\n", n->get(n));
   
   n->set(n, 9);
   
   printf("%d\n", n->get(n));

   //printf("%d\n", get(n));

   del_node(n);
}

   Note that we must pass the object itself as parameter for the functions so that it can access it attributes. The commented line would not be compiled correctly because the function get is not visible in this file.

   This is an easy way of doing pseudo-classes in C. There are some drawbacks of doing that because it does not have all the advantages of real classes.
   Some final conclusions are:
   - It is not possible, at least it is not easy, to inherit from another class. What can be done is to create the same functions in the new class that will call the functions of the other one, and it is useful to have an object of the base class as an attribute of the new one.
   - Private functions can be done by creating the functions in the definition file, i.e. the file with the static functions, without binding them to function pointers in the class.
   - As we have to pass the object itself as a parameter to its functions, if we pass another object of the same class by mistake it will not work properly.
   
by rcor

ċ
cclass.rar
(3k)
Rodrigo Caetano Rocha,
8 Jul 2011, 16:16
Comments