Shocking! C Language Can Achieve Object-Oriented Programming: Principles and Examples Fully Explained

Shocking! C Language Can Achieve Object-Oriented Programming: Principles and Examples Fully ExplainedCan C Language Achieve Object-Oriented Programming?

Introduction Object-Oriented Programming (OOP) is a programming paradigm centered around “objects,” organizing code through features such as encapsulation, inheritance, and polymorphism. While languages like C++ and Java natively support OOP, C, as a procedural language, can also achieve similar effects through clever design. This article will demonstrate how to simulate object-oriented programming in C with examples.

1. Core Concepts of Object-Oriented Programming1. Classes and Objects A class is a template for objects, defining the properties and methods of the objects; an object is an instance of a class. For example, a “Point” class can contain coordinate properties (x, y) and methods such as move and display coordinates. 2. Encapsulation By restricting direct access to internal data and exposing only necessary interfaces, code security and maintainability are improved. For instance, hiding the logic for calculating coordinates and only providing a move() method to modify the coordinates. 3. Inheritance A subclass inherits properties and methods from a superclass, achieving code reuse. For example, a “Circle” class can inherit basic coordinate properties from a “Shape” class and extend it with a radius property. 4. Polymorphism The same interface exhibits different behaviors on different objects. For instance, a “draw” method can implement different drawing logic for different shapes like circles and rectangles.

2. Implementing Object-Oriented Programming in C1. Simulating Classes and Objects Define class properties and methods using structures, and implement methods using function pointers:

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

// Define "class"
typedef struct Point {
    int x;
    int y;
    void (*move)(struct Point* self, int dx, int dy);
    void (*show)(struct Point* self);
} Point;

// Method implementation
void move(Point* self, int dx, int dy) {
    self->x += dx;
    self->y += dy;
}

void show(Point* self) {
    printf("Point: (%d, %d)\n", self->x, self->y);
}

// Constructor
Point* new_point(int x, int y) {
    Point* p = (Point*)malloc(sizeof(Point));
    p->x = x;
    p->y = y;
    p->move = move;
    p->show = show;
    return p;
}

// Destructor
void delete_point(Point* p) {
    free(p);
}

int main() {
    Point* p1 = new_point(0, 0);
    p1->show(p1);       // Output: (0, 0)
    p1->move(p1, 5, 3);
    p1->show(p1);       // Output: (5, 3)
    delete_point(p1);
    return 0;
}

2. Implementing Encapsulation Define the structure in a header file and expose only the interface functions:

// point.h
typedef struct Point Point;
Point* new_point(int x, int y);
void delete_point(Point* p);

3. Implementing Inheritance Simulate inheritance relationships through nested structures:

typedef struct {
    int x;
    int y;
} Shape; // Superclass

typedef struct {
    Shape shape; // Inherit superclass properties
    int radius;
    void (*draw)(struct Circle* self);
} Circle; // Subclass

void draw_circle(Circle* self) {
    printf("Circle at (%d, %d), radius=%d\n", 
           self->shape.x, self->shape.y, self->radius);
}

Circle* new_circle(int x, int y, int radius) {
    Circle* c = (Circle*)malloc(sizeof(Circle));
    c->shape.x = x;
    c->shape.y = y;
    c->radius = radius;
    c->draw = draw_circle;
    return c;
}

4. Implementing Polymorphism Use function pointers for dynamic method binding:

typedef struct {
    void (*draw)(void* shape);
} Shape;

void draw_shape(Shape* shape, void* obj) {
    shape->draw(obj);
}

int main() {
    Circle* c1 = new_circle(10, 10, 5);
    Shape shape = {.draw = (void (*)(void*))draw_circle};
    draw_shape(&shape, c1); // Output circle information
    return 0;
}

3. ConclusionStructures and function pointers are the core tools for simulating OOP in C, enabling the implementation of classes, encapsulation, and polymorphism. Nesting structures can simulate inheritance, but manual memory management and type conversion are required. Although the complexity of implementation is higher than in languages like C++, this design can significantly enhance code maintainability in embedded development or low-level systems.

The flexibility of C allows developers to transcend language limitations and integrate object-oriented concepts into procedural programming. This practice not only deepens the understanding of OOP but also enhances control over system design.

Finally

That’s all I want to share with you today. If you found it helpful, please remember to give it a thumbs up.

A permanent, free platform for sharing embedded technology knowledge~

Leave a Comment