Implementing object-oriented with C

Source: Internet
Author: User

Many development engineers are learning the C language from "Hello world!" The beginning, all know the C language of the pointer is a sword, do not pay attention to the injury from a. But its C language is absolutely a guru-level language, which is undeniable.
Because we developed the need to run on multiple platforms and need some object-oriented features, so close this article. Right to be a catalyst.

I. Overview
C language is a process-oriented programming language, and C + + adds many new mechanisms (inheritance, polymorphism, etc.) to the language level.
So here's the way to implement encapsulation, inheritance, and polymorphism using C language.


II. Basic Knowledge


1. Structural body


In C, an object is often encapsulated with a struct so that it is easy to manipulate objects such as: 1
Strcut point{
int x;
int y;
};




Structs can be nested. Thus one structure can be considered as a member of another struct:
struct Circle {
struct point point_;
int radius;
};




The structure is exactly the same as the following definition (including memory layout):
struct Circle {
int x;
int y;
int radius;
};




2. Function pointers


A function pointer is a pointer to the first address of the function (the function's function name is the first address of the function), and the function can be called by a function pointer.


such as functions:


int func (int a[], int n);


You can declare a function pointer like this:


Int (*pfunc) (int a[], int n);


This is used:


PFunc = func;


(*pfunc) (A, n); "or Pfunc (A, N)"


A typedef can be used to define a function pointer type, such as:


typdef Int (*func) (int a[], int n)


This can be used:


int Cal_a (FUNC fptr, int a[], int n)
{
Realization body ...
}


3, extern and static


extern and static are two modifiers in the C language, and extern can be used to modify a function or variable to indicate that the variable or function is defined in another file;
Static can also be used to modify a function or variable to indicate that the function or variable can only be used in the file. They can be used to hide or restrict access to data or functions.


Three, Package


In C, a struct + function pointer can be used to simulate the implementation of a class, whereas a variable defined with this structure is an object.


The main implication of encapsulation is to hide the internal behavior and information, and the user only sees the interface provided externally and the information that is exposed.


There are two ways to implement encapsulation:


1, the use of C language grammar. Declared in the header file, it is really defined in the C file.


This hides the internal information, because the external does not know the size of the memory that the object occupies, so you cannot statically create objects of that class, only the creation functions provided by the class can be created. The drawback of this approach is that inheritance is not supported because there is no information about the parent class in the subclass. Such as:


/**
* Header file for point Point.h (external interface)
*/
#ifndef Point_h
#define Point_h


extern const void * point; /* New (point, X, y); */


void Move (void * point, int dx, int dy);


struct Point {
const void * BASE; Inherit the base class, and put it in the first position, const is to prevent modification
int x, y; Coordinate
};


#define Point_x (P)(((const struct point *) (P)) x)
#define Point_y (P)(((const struct point *) (P))


#endif



Source file for Point point.c
#include <stdio.h>
#include "Point.h"
#include "Cnew.h"
#include "Base.h"


/**********point class's own constructor ***********/
static void * Point_new (void * _self, va_list * app) {
struct point * self = _self;
Self->x = Va_arg (*app, int);
Self->y = Va_arg (*app, int);
printf ("point_new self =%p \ n", self);
return self;
}


/**********point class's own destructor ***********/
Static void* point_delete (void * _self) {
printf ("Call Point_delete self =%p \ n", _self);
printf ("\ n");
return NULL;
}


/**********point class's own drawing function ***********/
static void Point_draw (const void * _self) {
const struct point * self = _self;
printf ("Point_draw at%d,%d \ n", self->x, Self->y);
}


void Move (void * _self, int dx, int dy) {
struct point * self = _self;
printf ("Call move self =%p \ n", _self);
Self->x + = DX;
Self->y + = dy;
}


static const struct Base _point = {sizeof (struct point), Point_new, Point_delete, Point_draw};
const void * point = &_Point;


Iv. inheritance


In the C language, you can take advantage of the fact that the "structure in memory layout is in a consistent order with the declaration of the structure" to implement inheritance.


For example, we want to design a drawing tool, which may involve the object has point (dot), Circle (circle), because the circle is composed of points, all can be considered as circle inherits from Point. In addition, point and circle require space applications, space release operations, and so on, all of which have common base class base.


#ifndef C_new_h
#define C_new_h


/**
* Memory Management class header file Cnew.h (external interface)
*/


void * CNEW (const void * base, ...);


void Cdelete (void * Item);


void Draw (const void * self);


#endif/* C_new_h */



/**
* Source files for memory management classes: CNEW.C
*/
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#include "Cnew.h"
#include "Base.h"


void * CNEW (const void * _class, ...) {
const struct BASE * base = _class;
void * p = calloc (1, base->size);
ASSERT (P);
* (CONST struct Base * *) p = base;
if (base->constructor) {
Va_list ap;
Va_start (AP, _class);
p = Base->constructor (P, &AMP;AP);
Va_end (AP);
}
return p;
}


void Cdelete (void * self) {
const struct Base * * cp = self;
if (self && *cp && (*CP)->destroy)
Self = (*CP)->destroy (self);
Free (self);
}


void Draw (const void * self) {
const struct BASE * CONST * CP = self;
ASSERT (self && *cp && (*CP)->draw);
(*CP)->draw (self);
}

/**
* Base class Base Internal header file BASE.R, externally hidden
*/
#ifndef Base_r
#define Base_r


#include <stdarg.h>


struct Base {
size_t size;
void * (*constructor) (void * Self, va_list * app); constructor function
void * (*destroy) (void * self);Destructors
void (*draw) (const void * self);Graphing function
};


#endif


/**
* Header file for point Point.h (external interface)
*/
#ifndef Point_h
#define Point_h


extern const void * point; /* New (point, X, y); */


void Move (void * point, int dx, int dy);


struct Point {
const void * BASE; Inherit the base class, and put it in the first position, const is to prevent modification
int x, y; Coordinate
};


#define Point_x (P)(((const struct point *) (P)) x)
#define Point_y (P)(((const struct point *) (P))


#endif


Source file for Point point.c
#include <stdio.h>
#include "Point.h"
#include "Cnew.h"
#include "Base.h"


/**********point class's own constructor ***********/
static void * Point_new (void * _self, va_list * app) {
struct point * self = _self;
Self->x = Va_arg (*app, int);
Self->y = Va_arg (*app, int);
printf ("point_new self =%p \ n", self);
return self;
}


/**********point class's own destructor ***********/
Static void* point_delete (void * _self) {
printf ("Call Point_delete self =%p \ n", _self);
printf ("\ n");
return NULL;
}


/**********point class's own drawing function ***********/
static void Point_draw (const void * _self) {
const struct point * self = _self;
printf ("Point_draw at%d,%d \ n", self->x, Self->y);
}


void Move (void * _self, int dx, int dy) {
struct point * self = _self;
printf ("Call move self =%p \ n", _self);
Self->x + = DX;
Self->y + = dy;
}


static const struct Base _point = {sizeof (struct point), Point_new, Point_delete, Point_draw};
const void * point = &_Point;


/**
* Circle's header file Circle.h (externally available interface)
*/


#ifndef Circle_h
#define Circle_h


#include "Point.h"


extern const void * Circle; /* New (Circle, X, Y, rad) */


struct Circle {
const struct point pbase; Inherit the point class, which needs to be placed first
int radius;
Int (*area) (void *self);Area, extension method
};


#define CIRCLE_AREA (P) (((const struct Circle *) (p)) area (p))


#endif




/**
* Circle's Source file circle.c
*/
#include <stdio.h>
#include "Circle.h"
#include "Cnew.h"
#include "Base.h"


/**********circle class's own extension function ***********/
static int Circle_area (void * _self) {
const struct Circle * self = _self;
printf ("Call Circle_area self =%p \ n", _self);
Return Self->radius * self->radius;
}


/**********circle class's own constructor ***********/
static void * Circle_new (void * _self, va_list * app) {
struct Circle * self = ((const struct Base *) point)->constructor (_self, app);
Self->radius = Va_arg (*app, int);
Self->area = Circle_area;
printf ("Call circle_new self =%p \ n", _self);
return self;
}


/**********circle class's own constructor ***********/
Static void* circle_delete (void * _self) {
printf ("Call Circle_delete self =%p \ n", _self);
printf ("\ n");
return NULL;
}


/**********circle class's own drawing function ***********/
static void Circle_draw (const void * _self) {
const struct Circle * self = _self;
int x = point_x (self);
int y = point_y (self);
printf ("Circle_draw at%d,%d rad%d \ n", x, Y, Self->radius);
}


static const struct Base _circle = {sizeof (struct Circle), circle_new, Circle_delete, Circle_draw};
const void * Circle = &_Circle;






/**
* Test function
*/


#include "Circle.h"
#include "Cnew.h"


int oo_main (int argc, char * * argv) {
void * p;
int i;
for (i = 0; i < 2; i++) {
if (i = = 0) {
p = cnew (Circle, 1, 2, 3);
Circle_area (P);
} else {
p = cnew (point, 1, 2);
}
Draw (P);
Move (P, 10, 20);
Draw (P);
Cdelete (P);
}
return 0;
}


/***********************************
* Test Results:
*
* Point_new self = 0x50a1d8
* Call Circle_new Self =0x50a1d8
* Circle_draw at 3 rad
* Call Move Self =0x50a1d8
* Circle_draw at 11,22 Rad 3
* Call Circle_delete Self =0x50a1d8
*
* Point_new self = 0x5096a0
* Point_draw at
* Call Move Self =0x5096a0
* Point_draw at 11,22
* Call Point_delete Self =0x5096a0
*
************************************/


V. Polymorphism


Can be used in the C language of the universal pointer void* to achieve polymorphism, followed by the above example:


Test MAIN.C

int oo_main (int argc, char * * argv) {
void * p;
int i;
for (i = 0; i < 2; i++) {
if (i = = 0) {
p = cnew (Circle, 1, 2, 3);
Circle_area (P);
} else {
p = cnew (point, 1, 2);
}
Draw (P);
Move (P, 10, 20);
Draw (P);
Cdelete (P);
}
return 0;
}


Vi. Summary


C language can simulate the implementation of object-oriented language features, including: polymorphism, inheritance, encapsulation, etc., now many open-source software has implemented these features in C language, including large open source database system PostgreSQL, portable C-Language object-oriented framework GObject, Wireless binary run environment brew. Using C language to achieve polymorphism, inheritance, encapsulation, can make the software has better readability, extensibility.


All the test code:


http://download.csdn.net/detail/andyhuabing/8475335


Implementing object-oriented with C

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.