美文网首页
C语言实现面向对象

C语言实现面向对象

作者: ShowMeCoding | 来源:发表于2023-04-12 23:11 被阅读0次

    一步步分析:C语言如何面向对象编程 - 知乎 (zhihu.com)
    C 语言实现面向对象编程_面向对象程序设计c语言_onlyshi的博客-CSDN博客

    Animal.h

    #ifndef _ANIMAL_H_
    #define _ANIMAL_H_
    
    //父类虚表的前置声明
    struct AnimalVTable;
    
    // 定义父类结构
    typedef struct {
        struct AnimalVTable* vptr; //虚表指针
        int age;
        int weight;
    } Animal;
    
    // 构造函数声明
    //显示定义this指针,当调用时主动把对象的地址传递给它
    void Animal_Ctor(Animal* this, int age, int weight); 
    
    //父类中的虚表
    struct AnimalVTable {
        void (*say)(Animal* this); //虚函数指针
    };
    
    //父类中实现的虚函数
    void Animal_Say(Animal* this);
    
    // 获取父类属性声明
    int Animal_GetAge(Animal* this);
    int Animal_GetWeight(Animal* this);
    
    #endif
    

    Animal.c

    #include "assert.h"
    #include "Animal.h"
    
    //父类中虚函数的具体实现
    static void _Animal_Say(Animal* this) {
        //因为父类中Animal是一个抽象的东西,不该被实例化
        //父类中的虚函数不应该被调用,也就是说子类必须实现这个虚函数
        //类似于C++中的纯虚函数
        assert(0);
    }
    
    // 父类构造函数实现
    void Animal_Ctor(Animal* this, int age, int weight)
    {
        //首先定义一个虚表
        static struct AnimalVTable animal_vtbl = { _Animal_Say };
        //让虚指针指向上面这个虚表
        this->vptr = &animal_vtbl;
        this->age = age;
        this->weight = weight;
    }
    
    //测试多态
    void Animal_Say(Animal* this) {
        //如果this实际指向一个子类Dog对象,那么this->vptr这个虚表指针指向子类自己的虚表
        //因此,this->vptr->say将会调用子类虚表中的函数
        this->vptr->say(this);
    }
    
    int Animal_GetAge(Animal* this)
    {
        return this->age;
    }
    
    int Animal_GetWeight(Animal* this)
    {
        return this->weight;
    }
    

    Dog.h

    #ifndef _DOG_H_
    #define _DOG_H_
    
    #include "Animal.h"
    //定义子类结构
    typedef struct {
        Animal parent; //第一个位置放置父类结构
        int legs;      //定义子类属性
    } Dog;
    
    //子类构造函数声明
    void Dog_Ctor(Dog* this, int age, int weight, int legs);
    
    //子类属性声明
    int Dog_GetAge(Dog* this);
    int Dog_GetWeight(Dog* this);
    int Dog_GetLegs(Dog* this);
    
    #endif
    

    Dog.c

    #include "Dog.h"
    
    //子类中虚函数的具体表现
    static void _Dog_Say(Dog* this) {
        printf("dog say hello!\n");
    }
    
    //子类构造函数
    void Dog_Ctor(Dog* this, int age, int weight, int legs) {
        //首先调用父类构造函数,初始化从父类继承的数据
        Animal_Ctor(&this->parent, age, weight);
        //定义子类自己的虚函数表
        static struct AnimalVTable dog_vtbl = { _Dog_Say };
        //把从父类中继承得到的虚表指针指向子类自己的虚表
        this->parent.vptr = &dog_vtbl;
        //然后初始化子类自己的数据
        this->legs = legs;
    }
    
    
    //子类构造函数声明
    int Dog_GetAge(Dog* this) {
        //age属性是继承而来,转发给父类中的获取属性函数
        return Animal_GetAge(&this->parent);
    }
    int Dog_GetWeight(Dog* this) {
        return Animal_GetWeight(&this->parent);
    
    }
    int Dog_GetLegs(Dog* this) {
        //直接返回子类的属性
        return this->legs;
    }
    

    main.c

    #include <stdio.h>
    #include "Animal.h"
    #include "Dog.h"
    
    int main() {
        //封装:描述数据的组织形式,把一个对象的所有属性组织在一起,c语言使用结构体
        //在栈上创建一个对象
        Animal a;
        //构造对象
        Animal_Ctor(&a, 1, 3);
        printf("age = %d, weight = %d \n",
            Animal_GetAge(&a),
            Animal_GetWeight(&a));
    
        //继承:子类通过继承父类,自动拥有父类的属性和方法,c语言主要注意内存模型
        Dog d;
        Dog_Ctor(&d, 1, 3, 4);
        printf("age = %d, weight = %d, legs = %d \n",
            Dog_GetAge(&d),
            Dog_GetWeight(&d),
            Dog_GetLegs(&d));
        //多态:描述一种动态行为,在C++中,只有通过基类引用或者指针,
        //去调用虚函数的时候才发生多态,C++内部通过一个虚表实现多态
        //如果一门语言只支持类,打不支持多态,只能说它是基于对象的,而不是面向对象的
        Dog dd;
        Dog_Ctor(&dd, 2, 2, 4);
        //把子类对象赋值给父类指针
        Animal* pa = &dd;
        //传递父类指针,将会调用子类中实现的虚函数
        Animal_Say(pa);
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:C语言实现面向对象

          本文链接:https://www.haomeiwen.com/subject/ychoddtx.html