Get started !
online LTE test
online C test

Updated or New
5G NR Data Rate calculator New
5G NR TBS calculator New
5G NR UE Registration New
Python programming
C++ programming
MIMO for 3GPP Developer - 2
Uplink power control
MIMO for 3GPP Developer
NR ARFCN and GSCN
5GS Interfaces



About
Feedback
Information Theory
Modulation
Multiple Access
DSP (wip)
OSI Model
Data Link layer
SS7
Word about ATM
GSM
GPRS
UMTS
WiMAX
LTE
CV2X
5G
Standard Reference
Reference books
Resources on Web
Miscellaneous
Mind Map
Magic MSC tool
Bar graph tool
C programming
C++ programming
Perl resources
Python programming
Javascript/HTML
MATLAB
ASCII table
Project Management

another knowledge site

3GPP Modem
Simulator


Sparkle At Office comic strip

Object Oriented Programming using C

C is meant to be for structured programming, but is object oriented programming possible with C ? Let us make an attempt at it. Here would be our approach: We will take a characteristic of OOP, implement it in C++ and then try to implement it in C.

First basic characteristic of OOP is of course Objects and their Methods.

Below is an example of C++ program which implement object called sphere.

File: sphere.hpp

  class sphere {
 
    public:
     sphere(int rad);
     int get_radius();
   
    private:
     int radius;
     
  };


File: sphere.cpp

  #include "sphere.hpp"
 
  sphere::sphere(int rad) {
    radius = rad;
  }
 
  int sphere::get_radius() {
    return radius;
  }


File: spheremain.cpp (to test)

  #include <stdio.h>
  #include "sphere.hpp"
 
  int main(void) {
 
   sphere *sphere1 = new sphere(30);
   printf( "Sphere 1 of radius %d\n", sphere1->get_radius() );
   return 1;
  }




The same can be implemented in C as below:
- C do not have built-in "constructor", so we have separate function sphere_constructor that will do the same.
- C do not support methods, so we use function binding.
- C do not have this pointer, we pass the pointer as first argument in methods.

File: sphere.h

  typedef struct sphere_struct sphere;
 
  struct sphere_struct {
   int (*get_radius)(sphere*);
   int radius;
  };
 
  void sphere_constructor(sphere* sptr, int rad);


File: sphere.c

  #include "sphere.h"
 
  static int intern_get_radius(sphere *sptr);
 
  void sphere_constructor(sphere *sptr, int rad) {
    sptr->get_radius = intern_get_radius;
    sptr->radius = rad;
  }
 
  int intern_get_radius(sphere *sptr) {
    return sptr->radius;
  }


File: spheremain.c

  #include <stdio.h>
  #include "sphere.h"
 
  int main(void) {
 
    sphere *sphere1 = (sphere*)malloc( sizeof( sphere ) );
    sphere_constructor(sphere1, 30);
    printf( "Sphere 1 of radius %d\n", sphere1->get_radius(sphere1) );
    return 1;
  }




Next OOP characteristic is Inheritance.

Below is an extension of above example in which we extend sphere to csphere (colored sphere).

File: csphere.hpp

  #include "sphere.hpp"
 
  #define CSPHERE_COL_LEN 4
 
  class csphere : public sphere {
 
  public:
   csphere(int rad, const char *color);
   char *get_color();
   
  private:
   char color[CSPHERE_COL_LEN];
 
  };
 
File: csphere.cpp

  #include "csphere.hpp"
  #include <string.h>
 
  csphere::csphere(int rad, const char *col)
          :sphere( rad ) {
    strncpy(color, col, CSPHERE_COL_LEN-1);
    color[CSPHERE_COL_LEN-1] = '\0';
  }
 
  char *csphere::get_color() {
    return color;
  }


File: spheremain.cpp

  #include <stdio.h>
  #include "csphere.hpp"
 
  int main(void) {
 
   sphere *sphere1 = new sphere(30);
   csphere *csphere1 = new csphere(20, "red");
 
   printf( "Sphere 1 of radius %d\n", sphere1->get_radius() );
   printf( "Colored sphere 1 of radius %d and color %s\n", csphere1->get_radius(), csphere1->get_color() );
 
   return 1;
  }


The same using C:
- C do not support inheritance, so in our csphere structure, we have sphere field.
- csphere structure will have duplicate methods from sphere.

File: csphere.h

  #include "sphere.h"
  #define CSPHERE_COL_LEN 4
 
  typedef struct csphere_struct csphere;
  struct csphere_struct {
   sphere *parent_sphere;
   int (*get_radius)(csphere*);
   char *(*get_color)(csphere*);
 
   char color[CSPHERE_COL_LEN];
  };
 
  void csphere_constructor(csphere* csptr, int rad, const char *col);


File: csphere.c

  #include "csphere.h"
  #include <string.h>
 
  static int intern_get_radius(csphere *csptr);
  static char *intern_get_color(csphere *csptr);
 
  void csphere_constructor(csphere *csptr, int rad, const char *col) {
 
    csptr->parent_sphere = (sphere*)malloc( sizeof( sphere ) );
    sphere_constructor(csptr->parent_sphere, rad);
    
    strncpy( csptr->color, col, CSPHERE_COL_LEN-1 );
    csptr->color[CSPHERE_COL_LEN-1] = '\0';
    csptr->get_color = intern_get_color;
    csptr->get_radius = intern_get_radius;
  }
 
  char *intern_get_color(csphere* csptr) {
    return csptr->color;
  }
 
  int intern_get_radius(csphere *csptr) {
    return csptr->parent_sphere->radius;
  }


File: spheremain.c

  #include <stdio.h>
  #include "csphere.h"
 
  int main(void) {
 
    sphere *sphere1 = (sphere*)malloc( sizeof( sphere ) );
    csphere *csphere1 = (csphere*)malloc( sizeof( csphere ) );
    
    sphere_constructor(sphere1, 30);
    csphere_constructor(csphere1, 20, "red");
    
    printf( "Sphere 1 of radius %d\n", sphere1->get_radius(sphere1) );
    printf( "Colored sphere 1 of radius %d and color %s\n", csphere1->get_radius(csphere1), csphere1->get_color(csphere1) );
 
    return 1;
  }


Next, we will have look at Polymorphism.

Below C++ example, adds sphere comparison which is overloaded by csphere.

File: sphere.hpp

  class sphere {
 
    public:
     sphere(int rad);
     int get_radius();
     bool operator==(const sphere &s1) 
     { 
       return (radius == s1.radius);
     }
   
    private:
     int radius;
  };


File: csphere.hpp

  #include "sphere.hpp"
  #include <string.h>
  #define CSPHERE_COL_LEN 4
 
  class csphere : public sphere {
 
    public:
     csphere(int rad, const char *color);
     char *get_color();
     bool operator==(const csphere &cs1) 
     { 
       return ( ( (*(sphere*)this) == (*(sphere*)&cs1) ) && 
                !(strcmp(color, cs1.color))              );
     }
 
    private:
     char color[CSPHERE_COL_LEN];
 
  };


File: spheremain.cpp

  #include <stdio.h>
  #include "csphere.hpp"
 
  int main(void) {
 
   sphere *sphere1 = new sphere(30);
   csphere *csphere1 = new csphere(20, "red");
   sphere *sphere2 = new sphere(30);
   csphere *csphere2 = new csphere(20, "red");
   
   printf( "Sphere 1 of radius %d\n", sphere1->get_radius() );
   printf( "Colored sphere 1 of radius %d and color %s\n", csphere1->get_radius(), csphere1->get_color() );
   printf( "Sphere 2 of radius %d\n", sphere2->get_radius() );
   printf( "Colored sphere 2 of radius %d and color %s\n", csphere2->get_radius(), csphere2->get_color() );
   
   if( *sphere1 == *sphere2 ) {
     printf( "Sphere1 is equal to Sphere2\n" );
   } else {
     printf( "Sphere1 is *not* equal to Sphere2\n" );
   }
 
   if( *csphere1 == *csphere2 ) {
      printf( "Colored sphere 1 is equal to colored sphere 2\n" );
   } else {
      printf( "Colored sphere 1 is *not* equal to colored sphere 2\n" );
   }
 
   return 1;
  }


The same now using C:
- Equal-to operator behaviour can not be changed in C, so we use function instead. Though it is not as good readable as C++ (spheremain.cpp) implementation, it serves the purpose.

File: sphere.h

  typedef struct sphere_struct sphere;
 
  struct sphere_struct {
 
   int (*get_radius)(sphere*);
   int (*equal_to)(sphere*, sphere*);
   
   int radius;
  };
 
  void sphere_constructor(sphere* sptr, int rad);


File: sphere.c

  #include "sphere.h"
 
  static int intern_get_radius(sphere *sptr);
  static int intern_equal_to(sphere *s1, sphere *s2);
 
  void sphere_constructor(sphere *sptr, int rad) {
 
    sptr->get_radius = intern_get_radius;
    sptr->equal_to = intern_equal_to;
    sptr->radius = rad;
    
  }
 
  int intern_get_radius(sphere *sptr) {
    return sptr->radius;
  }
 
  int intern_equal_to(sphere *s1, sphere *s2) {
    return (s1->radius == s2->radius);
  }


File: csphere.h

  #include "sphere.h"
  #define CSPHERE_COL_LEN 4
 
  typedef struct csphere_struct csphere;
  struct csphere_struct {
 
   sphere *parent_sphere;
   int (*get_radius)(csphere*);
   const char *(*get_color)(csphere*);
   int (*equal_to)(csphere*, csphere*);
 
   char color[CSPHERE_COL_LEN];
  };
 
  void csphere_constructor(csphere* csptr, int rad, const char *col);


File: csphere.c

  #include "csphere.h"
  #include <string.h>
 
  static int intern_get_radius(csphere *csptr);
  static const char *intern_get_color(csphere *csptr);
  static int intern_equal_to(csphere *cs1, csphere *cs2);
 
  void csphere_constructor(csphere *csptr, int rad, const char *col) {
 
    csptr->parent_sphere = (sphere*)malloc( sizeof( sphere ) );
    sphere_constructor(csptr->parent_sphere, rad);
    
    strncpy( csptr->color, col, CSPHERE_COL_LEN-1 );
    csptr->color[CSPHERE_COL_LEN-1] = '\0';
    csptr->get_color = intern_get_color;
    csptr->get_radius = intern_get_radius;
    csptr->equal_to = intern_equal_to;
  }
 
  const char *intern_get_color(csphere* csptr) {
    return csptr->color;
  }
 
  int intern_get_radius(csphere *csptr) {
    return csptr->parent_sphere->radius;
  }
 
  int intern_equal_to(csphere *cs1, csphere *cs2) {
    return( (cs1->parent_sphere->equal_to(cs1->parent_sphere, cs2->parent_sphere) ) &&
            !(strcmp(cs1->color, cs2->color))                                       );
  }


File: spheremain.c

  #include <stdio.h>
  #include "csphere.h"
 
  int main(void) {
 
    sphere *sphere1 = (sphere*)malloc( sizeof( sphere ) );
    csphere *csphere1 = (csphere*)malloc( sizeof( csphere ) );
    sphere *sphere2 = (sphere*)malloc( sizeof( sphere ) );
    csphere *csphere2 = (csphere*)malloc( sizeof( csphere ) );
    
    sphere_constructor(sphere1, 30);
    csphere_constructor(csphere1, 20, "red");
    sphere_constructor(sphere2, 30);
    csphere_constructor(csphere2, 20, "red");
    
    printf( "Sphere 1 of radius %d\n", sphere1->get_radius(sphere1) );
    printf( "Colored sphere 1 of radius %d and color %s\n", csphere1->get_radius(csphere1), csphere1->get_color(csphere1) );
    printf( "Sphere 2 of radius %d\n", sphere1->get_radius(sphere2) );
    printf( "Colored sphere 2 of radius %d and color %s\n", csphere2->get_radius(csphere2), csphere2->get_color(csphere2) );
 
    if( sphere1->equal_to( sphere1, sphere2 ) ) {
      printf( "Sphere 1 is equal to sphere 2\n" );
    } else {
      printf( "Sphere 1 is *not* equal to sphere 2\n" );
    }
    
    if( csphere1->equal_to( csphere1, csphere2 ) ) {
      printf( "Colored sphere 1 is equal to colored sphere 2\n" );
    } else {
      printf( "Colored sphere 1 is *not* equal to colored sphere 2\n" );
    }
    
    return 1;
  }


But there is a catch, our C implementation won't be able compare sphere with csphere ! In C++, if csphere and sphere comparison will automatically call comparison operation from parent object i.e sphere object. Following lines of code would go ahead and compare, but corresponding C code won't work.



File: spheremain.cpp

   if( *sphere1 == *csphere1 ) {
      printf( "Sphere 1 is equal to colored sphere 1\n" );
   } else {
      printf( "Sphere 1 is *not* equal to colored sphere 1\n" );
   }


File: spheremain.c

    if( sphere1->equal_to( sphere1, csphere1 ) ) {
      printf( "Sphere 1 is equal to colored sphere 1\n" );
    } else {
      printf( "Sphere 1 is *not* equal to colored sphere 1\n" );
    }


Here is alternative then: we will have additional separate function to compare sphere with csphere.



  int all_spheres_equal_to( sphere *sptr, csphere *csptr ) {
    return (sptr->radius == csptr->parent_sphere->radius);
  }


File: spheremain.c

  int main(void) {
  .
  .
    if( all_spheres_equal_to( sphere1, csphere1 ) ) {
      printf( "Sphere 1 is equal to colored sphere 1\n" );
    } else {
      printf( "Sphere 1 is *not* equal to colored sphere 1\n" );
    }
  .
  .
  }

References: For OOP concepts - An introduction to OOP by Timothy Budd.

Copyright © Samir Amberkar 2010-11§

C Programming Guide « C guide Index » Object Oriented Programming using C - 2