您的位置:

C语言面向对象详解

一、什么是面向对象编程

面向对象编程(Object-Oriented Programming)是一种编程范式,它将现实世界中的事物(即对象)抽象成计算机程序中的数据类型,并通过定义对象之间的关系和交互来实现程序的设计和实现。

与面向过程编程相比,面向对象编程更加注重行为和关系的表达,能够更加直观地描述复杂的系统,并提供了良好的封装性、继承性和多态性等特性。

二、C语言的面向对象支持

虽然C语言没有提供原生的面向对象支持,但通过一些技巧和手段,我们仍然可以用C语言来实现基本的面向对象特性。

1. 数据抽象

数据抽象(Data Abstraction)是面向对象编程的核心思想之一,它通过定义抽象数据类型来隐藏数据的实现细节,使得用户只需关注数据的行为而不需要关注其具体实现方式。

C语言通过结构体和函数指针等手段可以很好地实现数据抽象。下面是一个基本的数据抽象例子:

// 定义抽象数据类型
typedef struct _Person
{
    char *name;
    int age;
    void (*say_hello)();
} Person;

// 定义函数指针
typedef void (*SayHelloFunc)();

// 实现具体行为
void say_hello_cn()
{
    printf("你好,世界!\n");
}

void say_hello_en()
{
    printf("Hello World!\n");
}

// 初始化对象
Person person = {"Tom", 20, say_hello_cn};

// 调用方法
person.say_hello(); // 输出"你好,世界!"

// 修改对象的行为
person.say_hello = say_hello_en;
person.say_hello(); // 输出"Hello World!"

2. 封装

封装(Encapsulation)是指将数据和行为组合成一个单独的单元,并限制其他代码直接访问和修改这个单元的方式。

C语言通过结构体和函数指针等手段可以实现简单的封装。下面是一个封装的例子:

// 定义结构体,用于存储一些私有数据
typedef struct _LinkedListNode {
    int data;
    struct _LinkedListNode *next;
    struct _LinkedListNode *prev;
} LinkedListNode;

// 定义公共接口,只暴露部分行为给用户
typedef struct _LinkedList {
    LinkedListNode *head;
    LinkedListNode *tail;
    int size;

    void (*insert)(struct _LinkedList *self, int data);
    void (*remove)(struct _LinkedList *self, int data);
} LinkedList;

// 实现接口的具体行为,使用函数指针调用私有方法
static void _insert(LinkedList *self, int data)
{
    LinkedListNode *node = malloc(sizeof(LinkedListNode));
    node->data = data;
    node->prev = self->tail;
    node->next = NULL;

    if (self->tail == NULL)
    {
        self->head = node;
        self->tail = node;
    }
    else
    {
        self->tail->next = node;
        self->tail = node;
    }

    self->size++;
}

static void _remove(LinkedList *self, int data)
{
    LinkedListNode *current = self->head;

    while (current != NULL)
    {
        if (current->data == data)
        {
            if (current->prev != NULL)
            {
                current->prev->next = current->next;
            }
            else
            {
                self->head = current->next;
            }

            if (current->next != NULL)
            {
                current->next->prev = current->prev;
            }
            else
            {
                self->tail = current->prev;
            }

            free(current);
            self->size--;
            break;
        }

        current = current->next;
    }
}

// 使用工厂函数封装创建对象的细节
LinkedList *LinkedList_create()
{
    LinkedList *list = malloc(sizeof(LinkedList));
    list->head = NULL;
    list->tail = NULL;
    list->size = 0;

    list->insert = _insert;
    list->remove = _remove;

    return list;
}

// 客户端代码
LinkedList *list = LinkedList_create();
list->insert(list, 1);
list->insert(list, 2);
list->insert(list, 3);
list->remove(list, 2);

3. 继承

继承(Inheritance)是指通过创建一个子类来继承父类的属性和方法,并在其基础上增加、修改或删除一些行为。

在C语言中,我们可以使用结构体嵌套和函数指针来实现简单的继承。下面是一个继承的例子:

// 定义父类,包含一些共有的行为
typedef struct _Animal
{
    char *name;

    void (*eat)();
    void (*sleep)();
} Animal;

// 定义子类,包含一些新增或者修改的行为
typedef struct _Cat
{
    Animal parent;
    char *color;

    void (*play)();
} Cat;

// 实现父类的行为
void animal_eat()
{
    printf("Animal is eating...\n");
}

void animal_sleep()
{
    printf("Animal is sleeping...\n");
}

// 实现子类的行为
void cat_play()
{
    printf("Cat is playing...\n");
}

// 工厂函数创建对象
Cat* cat_create(char *name, char *color)
{
    Cat *cat = malloc(sizeof(Cat));

    cat->parent.name = name;
    cat->parent.eat = animal_eat;
    cat->parent.sleep = animal_sleep;

    cat->color = color;
    cat->play = cat_play;

    return cat;
}

// 客户端代码
Cat *cat = cat_create("Tom", "white");
printf("name=%s, color=%s\n", cat->parent.name, cat->color); // 输出"name=Tom, color=white"
cat->parent.eat(); // 输出"Animal is eating..."
cat->play(); // 输出"Cat is playing..."

4. 多态

多态(Polymorphism)是指不同的对象可以对同一消息做出不同的响应。

在C语言中,通过函数指针和结构体嵌套等技巧可以实现简单的多态。下面是一个多态的例子:

// 定义共有接口
typedef struct _Shape
{
    char *type;

    float (*area)(struct _Shape *self);
} Shape;

// 定义子类,实现具体的行为
typedef struct _Rectangle
{
    Shape parent;
    float width;
    float height;
} Rectangle;

float rectangle_area(Rectangle *self)
{
    return self->width * self->height;
}

// 定义子类,实现具体的行为
typedef struct _Circle
{
    Shape parent;
    float radius;
} Circle;

float circle_area(Circle *self)
{
    return 3.14 * self->radius * self->radius;
}

// 工厂函数创建对象
Rectangle *rectangle_create(float width, float height)
{
    Rectangle *shape = malloc(sizeof(Rectangle));
    shape->parent.type = "Rectangle";
    shape->parent.area = (float (*)(Shape *))rectangle_area;
    shape->width = width;
    shape->height = height;

    return shape;
}

Circle *circle_create(float radius)
{
    Circle *shape = malloc(sizeof(Circle));
    shape->parent.type = "Circle";
    shape->parent.area = (float (*)(Shape *))circle_area;
    shape->radius = radius;

    return shape;
}

// 客户端代码
Shape *shapes[2];
shapes[0] = (Shape *)rectangle_create(10, 20);
shapes[1] = (Shape *)circle_create(20);

for (int i = 0; i < 2; i++)
{
    printf("%s's area=%f\n", shapes[i]->type, shapes[i]->area(shapes[i]));
}