C语言实现面向对象的方法详解

发布时间 2023-12-23 20:25:07作者: 流水灯

结构体替代类

使用结构体来封装变量和函数,即可实现类似对象的功能。其中,结构体包含变量和函数指针,变量用于存储成员变量的值,函数指针用于实现成员函数的功能。而每个对象的变量是独立的,因此可以使用这种方法实现类似对象的功能。

下面是一个例子,以封装一个“人”的结构体为例:

typedef struct {
    char *name;
    int age;
    void (*speak)(const char *);
} Person;

void speak_func(const char *str) {
    printf("%s\n", str);
}

Person *new_person(char *name, int age) {
    Person *p = malloc(sizeof(Person));
    p->name = name;
    p->age = age;
    p->speak = speak_func;
    return p;
}

void destroy_person(Person *p) {
    free(p);
}

void main() {
    Person *p = new_person("Tom", 18);
    p->speak("Hello world!");   //输出:Hello world!
    destroy_person(p);
}

上述例子中,使用结构体Person封装了“人”的信息,其中包含两个成员变量和一个成员函数指针。函数指针speak指向函数speak_func,用于输出“人”的话语。通过new_person()函数创建一个新的“人”对象,人对象的变量是独立存储的。最后通过destroy_person()函数销毁“人”对象。

继承和多态

继承是面向对象的一个重要特性,允许子类继承父类的成员变量和成员函数,并可以自行定义新的成员变量和成员函数,因此可以实现代码的重用。

多态是面向对象中的另一个重要特性,指父类指针可以指向子类对象,从而调用子类重写的成员函数,实现代码的灵活性。

在C语言中,可以通过定义不同的结构体实现类的继承关系,并使用函数指针来实现多态。

下面是一个例子,以封装一个“动物”的父类和两个子类“狗”和“猫”为例:

typedef struct _Animal {
    const char *name;
    void (*speak)(struct _Animal *);
} Animal;

void speak(Animal *animal) {
    printf("%s speaks\n", animal->name);
}

typedef struct {
    Animal base;
} Dog;

void dog_speak(Dog *dog) {
    printf("%s barks\n", dog->base.name);
}

void init_dog(Dog *dog, const char *name) {
    dog->base.name = name;
    dog->base.speak = (void (*)(Animal *)) dog_speak;
}

typedef struct {
    Animal base;
} Cat;

void cat_speak(Cat *cat) {
    printf("%s meows\n", cat->base.name);
}

void init_cat(Cat *cat, const char *name) {
    cat->base.name = name;
    cat->base.speak = (void (*)(Animal *)) cat_speak;
}

void main() {
    Dog d;
    Cat c;
    init_dog(&d, "Dog");
    init_cat(&c, "Cat");

    Animal *pDog = (Animal*)(&d);
    Animal *pCat = (Animal*)(&c);

    pDog->speak(pDog);    //输出:Dog barks
    pCat->speak(pCat);    //输出:Cat meows
}

上述例子中,定义了一个“动物”的父类和两个子类“狗”和“猫”。通过定义不同的结构体实现类的继承关系。其中,“动物”的父类包含成员变量name和成员函数指针speak,成员函数speak使用结构体指针作为参数,指向不同的子类实现。

通过init_dog()和init_cat()函数分别初始化“狗”和“猫”对象,其中“狗”对象继承了“动物”的父类,并自定义了成员函数speak()的实现,输出“狗”叫声;“猫”对象同理。

最后通过定义Animal类型的指针指向Dog和Cat实例实现多态。pDog和pCat指向不同的子类实例,调用speak函数时分别输出“狗”声和“猫”声。