从面向过程到面向对象——C语言实面向对象编程特性

定义:(来自百度百科)
面向过程(ProcedureOriented)是一种以过程为中心的编程思想。这些都是以什么正在发生为主要目标进行编程,不同于面向对象的是谁在受影响。与面向对象明显的不同就是封装、继承、类。简写为POP。

两种编程思想的比较:

  • 面向过程(C语言)
    就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。在这里插入图片描述

  • 面向对象(c++,c#,java,delphi)
    是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。
    在这里插入图片描述

1. 封装 (Encapsulation)

目标:隐藏数据的具体实现,只暴露必要的接口给外部使用。

示例:定义一个类并封装其成员

myclass.h

#ifndef MYCLASS_H
#define MYCLASS_H

// 声明不透明类型
typedef struct MyClass MyClass;

// 接口函数声明
MyClass* MyClass_new(int value);
void MyClass_printValue(MyClass* self);
void MyClass_destroy(MyClass* self);

#endif // MYCLASS_H

myclass.c

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

// 定义结构体,并将其细节隐藏在 .c 文件中
struct MyClass {
    int value;
};

// 构造函数
MyClass* MyClass_new(int v) {
    MyClass* self = (MyClass*)malloc(sizeof(MyClass));
    if (!self) return NULL;
    self->value = v;
    return self;
}

// 成员函数
void MyClass_printValue(MyClass* self) {
    printf("Value: %d\n", self->value);
}

// 析构函数
void MyClass_destroy(MyClass* self) {
    free(self);
}

main.c

#include "myclass.h"

int main() {
    MyClass* obj = MyClass_new(42);
    MyClass_printValue(obj);
    MyClass_destroy(obj);
    return 0;
}

2. 继承 (Inheritance)

目标:通过组合的方式模拟子类从父类继承属性和行为。

示例:模拟继承

baseclass.h

#ifndef BASECLASS_H
#define BASECLASS_H

typedef struct BaseClass BaseClass;

BaseClass* BaseClass_new(int base_value);
void BaseClass_printValue(BaseClass* self);
void BaseClass_destroy(BaseClass* self);

#endif // BASECLASS_H

baseclass.c

#include "baseclass.h"
#include <stdlib.h>

struct BaseClass {
    int base_value;
};

BaseClass* BaseClass_new(int v) {
    BaseClass* self = (BaseClass*)malloc(sizeof(BaseClass));
    if (!self) return NULL;
    self->base_value = v;
    return self;
}

void BaseClass_printValue(BaseClass* self) {
    printf("Base Value: %d\n", self->base_value);
}

void BaseClass_destroy(BaseClass* self) {
    free(self);
}

derivedclass.h

#ifndef DERIVEDCLASS_H
#define DERIVEDCLASS_H

#include "baseclass.h"

typedef struct DerivedClass DerivedClass;

DerivedClass* DerivedClass_new(int base_value, int derived_value);
void DerivedClass_printValues(DerivedClass* self);
void DerivedClass_destroy(DerivedClass* self);

#endif // DERIVEDCLASS_H

derivedclass.c

#include "derivedclass.h"
#include <stdlib.h>

struct DerivedClass {
    BaseClass base;  // 模拟继承基类
    int derived_value;
};

DerivedClass* DerivedClass_new(int bv, int dv) {
    DerivedClass* self = (DerivedClass*)malloc(sizeof(DerivedClass));
    if (!self) return NULL;
    self->base.base_value = bv;
    self->derived_value = dv;
    return self;
}

void DerivedClass_printValues(DerivedClass* self) {
    BaseClass_printValue((BaseClass*)&self->base);  // 调用基类方法
    printf("Derived Value: %d\n", self->derived_value);
}

void DerivedClass_destroy(DerivedClass* self) {
    free(self);
}

main.c

#include "derivedclass.h"

int main() {
    DerivedClass* obj = DerivedClass_new(10, 20);
    DerivedClass_printValues(obj);
    DerivedClass_destroy(obj);
    return 0;
}

3. 多态 (Polymorphism)

目标:允许不同类型的对象通过相同的接口调用不同的实现。

示例:使用函数指针实现多态

animal.h

#ifndef ANIMAL_H
#define ANIMAL_H

typedef void (*PrintFunc)(void*);

typedef struct Animal Animal;

Animal* Animal_new(PrintFunc p);
void Animal_print(Animal* self);
void Animal_destroy(Animal* self);

#endif // ANIMAL_H

animal.c

#include "animal.h"
#include <stdlib.h>

struct Animal {
    PrintFunc print;
};

Animal* Animal_new(PrintFunc p) {
    Animal* self = (Animal*)malloc(sizeof(Animal));
    if (!self) return NULL;
    self->print = p;
    return self;
}

void Animal_print(Animal* self) {
    if (self->print) {
        self->print(self);
    }
}

void Animal_destroy(Animal* self) {
    free(self);
}

dog.c

#include "animal.h"
#include <stdio.h>

void Dog_print(void* self) {
    printf("Woof!\n");
}

Animal* Dog_new() {
    return Animal_new(Dog_print);
}

cat.c

#include "animal.h"
#include <stdio.h>

void Cat_print(void* self) {
    printf("Meow!\n");
}

Animal* Cat_new() {
    return Animal_new(Cat_print);
}

main.c

#include "animal.h"
#include "dog.c"  // 注意:通常应该包含头文件而不是源文件,这里为了简化演示
#include "cat.c"  // 注意:通常应该包含头文件而不是源文件,这里为了简化演示

int main() {
    Animal* dog = Dog_new();
    Animal* cat = Cat_new();

    Animal_print(dog);  // 输出 "Woof!"
    Animal_print(cat);  // 输出 "Meow!"

    Animal_destroy(dog);
    Animal_destroy(cat);

    return 0;
}

4. 抽象 (Abstraction)

目标:提供高层次的接口,隐藏底层复杂性。

示例:通过接口函数实现抽象

我们已经在上述例子中展示了这一点,即通过 myclass.h 提供高层次的接口,而将具体的实现隐藏在 myclass.c 中。用户只需要知道如何创建、操作和销毁对象,而不必关心内部是如何工作的。

总结

通过以上具体示例,我们可以看到如何在C语言中实现面向对象编程的关键特性:

  • 封装:通过将数据和操作数据的方法绑定在一起,并限制对数据的直接访问。
  • 继承:通过组合现有结构体来扩展功能,模拟子类从父类继承属性和行为。
  • 多态:利用函数指针让不同类型的对象共享同一个接口,但表现出不同的行为。
  • 抽象:提供简洁的接口,隐藏复杂的实现细节,让用户不必了解底层机制。

这些技术使得C语言也能以一种面向对象的方式来设计和编写程序,虽然不如真正的面向对象语言那么直观,但在需要的时候是非常有效的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值