• C语言模拟类的一个实例


    #include <stdio.h>
    #include <stdlib.h>
    
    /*用c语言模拟面向对象操作 修改:张亚雄
    
    C语言中的结构体是后来面向对象编程中的类的启蒙师傅。
    
    只不过很遗憾,丹尼斯忘记把函数放进结构体里面了。要不然后来也就没有java和C#什么事了。
    对象具有属性和方法,一般用类来来封装属性和方法。
    C语言是面向过程的编程语言,那么,它能不能借用面向对象的思路来进行程序设计呢?答案是可以。
    这里尝试使用结构体和指针来实现这个想法。不过实例一只实现了属性的封装。该程序正常运行
    实例一
    先定义一个结构体
    */
    
    
    
    struct Person
    {
        char* name;
        int age;
        int height;
        int weight;
    }person,*p; //并没有使用,思考为什么?
    
    /*
    下面是一个造人的函数,可以存储对象的属性,但是还没有方法。返回的是一个结构体指针变量。造人函数有4个参数。
    这些参数传递给内部的结构体成员进行赋值,这相当于给对象的属性赋值。
    这个结构体变量在函数中被maloco函数配置到了内存的一个区域,
    maloco函数会返回一个指针给结构体指针变量who。
    在函数内部使用这个结构体指针变量who给结构体成员赋值。
    然后把这个指针变量返出函数外部。
    */
    struct Person* Create_person(const char* name,int age,int height,int weight)
    {
        struct Person* who = malloc(sizeof(struct Person));
    /*用内存分配函数maloco开辟一块区域,大小由关键字sizeof决定  */
            /*该malodo函数会返回一个无类型指针变量*/
    /*把malodo函数返回的无类型的指针赋值给结构体指针变量who。赋值的同时会进行强制类型转换。*/
    /*这一个表达式包含了很多知识点,能看懂的童鞋说明有一定的功力*/
        who->name=name;    //给结构体内部的成员赋值
        who->age=age;
        who->height=height;
        who->weight=weight;
        return who;      //返回一个指针
    }
    //当调用上面这个函数的时候,通过参数把数据传递进去,感觉像是给类的属性赋值。
    //怎么“杀人”呢?
    void Destroy_person(struct Person* who)
    {
        free(who->name); // be carefull  ,只杀一个姓名?
        free(who);      //通过指针释放这个内存区域
    }
    //输出“人”的信息的函数:
    void Print_person(struct Person* who)
    {
        printf("Name:%s
    ",who->name);
        printf("Age:%d
    ",who->age);
        printf("height:%d
    ",who->height);
        printf("weight:%d
    ",who->weight);
    }
    //main.最后测试一下:
    
    int main(int argc, char *argv[])
    {
        // make two people structures  造两个人:joe 和frank。通过参数赋值。
        struct Person *joe = Create_person( "Joe Alex", 32, 64, 140);  //给joe初始化赋值,数据被保存在一个结构体里
        struct Person *frank = Create_person( "Frank Blank", 20, 72, 180);
    //可以用这个表达式不断地造人
        printf("c语言模拟面向对象编程
    ");
        // print them out and where they are in memory
        printf("Joe is at memory location %p:
    ", joe);//打印joe的地址,注意%p符号。
        Print_person(joe);  //打印joe的数据
        printf("**********************************
    ");
        printf("Frank is at memory location %p:
    ", frank); //打印joe的地址,注意%p符号。
        Print_person(frank);
        printf("*修改数据 and print them again*
    ");
        // make everyone age 20 years and print them again
        //修改joe的数据
        joe->age += 20;
        joe->height -= 2;
        joe->weight += 40;
        Print_person(joe);  //再次打印joe的修改过的数据
        printf("***再次打印joe的修改过的数据***
    ");
        frank->age += 20;
        frank->weight += 20;
        Print_person(frank);
        printf("**再次打印frank的修改过的数据******
    ");
        // destroy them both so we clean up
        Destroy_person(joe);  //杀死joe。真实的含义是释放内存
        Destroy_person(frank);  //杀死frank
        printf("space is free
    ");
        //可以添加检查指针是否为空的语句。
        return 0;
    }

     | 下面看一下我自己的实现方法:

    文件 User.h

    void PersonFunction();

    文件 User.c

    #include "User.h"
    #include<stdio.h>
    #include<limits.h>
    #include <stdlib.h>
    /*
        
        猜想验证2:造一个假的类
            思考:
                类有哪些特征?
                1. 有成员变量
                2. 有行为
                3. 有构造方法
    
            思路:
                用C里面的结构体来做
    
            补充:
                研究一下C里面的不定参函数
    
    */
    //结构体声明
    typedef struct {
        int a;
        int b;
        void (*PersonFunctionPointer)(void);//方法指针
    }Person;
    
    Person* Person_(int a, int b);//相当于构造方法
    
    
    
    
    Person* Person_(int a, int b) {//相当于构造方法
        Person* person = (Person*)malloc(sizeof(Person));
        person->a = a;
        person->b = b;
        person->PersonFunctionPointer = &PersonFunction;
        return person;
    
    }
    bool freePerson(Person* person) {//对象销毁的方法
        free(person);
        person = NULL;
        return person == NULL ? true : false;
    }
    void sayHi(Person* person) {
        printf("Hi I am Person.sayHi()...
    ");
        printf("a is:%d
    ", person->a);
        printf("b is:%d
    ", person->b);
    }
    int main() {
    
        Person* person = Person_(1, 1);
        person->a;//相当于成员变量
        person->PersonFunctionPointer();//相当于成员方法
    
        printf("free之前这个指针的值是:%p
    ", person);
        freePerson(person);
    
        printf("free之后这个指针的值是:%p
    ", person);
    
        getchar();
        return 1;
    
    
    }
    
    
    
    void PersonFunction()
    {
        printf("大家好,我是PersonFunction
    ");
    }

     | 例子2 与上一个相似

    User.h

    typedef struct {
        int a;
        int b;
        void(*sayHi_P)();
        void(*toString_P)();
        
    }Emp;
    
    
    void sayHi();
    void toString();
    Emp* Emp_(int a,int b);

    User.c

    #include "User.h"
    #include<stdio.h>
    #include<stdlib.h>
    
    int main() {
        Emp* emp = Emp_(2,1); //第一步 创建这个对象
        printf("a is:%d
    ",emp->a);//
        emp->sayHi_P();//第二步:使用这个对象
        emp->toString_P();
      
       free(emp);//释放内存 //第三步:销毁这个对象,并将其值设置为NULL
       emp = NULL;//并将其指向NULL
    getchar();
    return 1; } void sayHi() { printf("I am sayHi... "); } void toString() { printf("I am toString... "); } Emp* Emp_(int a, int b) { Emp* ep = (Emp*)malloc(sizeof(Emp)); ep->a = a; ep->b = b; ep->sayHi_P = sayHi; ep->toString_P = toString; return ep; }

     | 例子3 上一个例子的升级版

    User.h

    typedef struct {
        int empNum;
        double money;
    
    }EmpData;
    
    typedef struct {
        int a;
        int b;
        void(*sayHi_P)();
        void(*toString_P)();
        EmpData* empData;
    }Emp;
    
    
    void sayHi();
    void toString();
    Emp* Emp_(int a,int b);

    User.c

    #include "User.h"
    #include<stdio.h>
    #include<stdlib.h>
    
    int main() {
        Emp* emp = Emp_(1,1);
        int a = emp->a;
        EmpData* empData= (emp->empData);
        emp->sayHi_P();
        a = empData->empNum = 1011;
        
        printf("empNum is:%d
    ", empData->empNum);
        getchar();
        return 1;
    }
    
    
    
    
    
    
    void sayHi()
    {
        printf("I am sayHi...
    ");
    }
    
    void toString()
    {
        printf("I am toString...
    ");
    }
    
    Emp* Emp_(int a, int b)
    {
        Emp* ep = (Emp*)malloc(sizeof(Emp));
        ep->a = a;
        ep->b = b;
        ep->empData = (EmpData*)(malloc(sizeof(EmpData)));
        ep->sayHi_P = sayHi;
        ep->toString_P = toString;
        return ep;
    
    }

     | 例子4 增加了释放对象的方法

    User.h:

    #pragma once
    #ifndef USER_H
        #define USER_H
    
    //*********************************************************
    #ifndef _INC_STDIO
        #include<stdio.h>
    #endif
    
    #ifndef _INC_STDLIB
        #include<stdlib.h>
    #endif
    typedef struct {
        int age;
        void (*sayHi)(int);
        void(*intP)(int*);
        void(*testF1)(void*);
        void(*freeUser)(void**);//重点看这里
        
    }User;
    
    void sayHi(int i);
    
    User* userInit(int age);
    void int_P(int* intP);
    void testF1(void* voidP);
    void freeUser(void** userPP);
    
    
    
    
    
    //*********************************************************
    #endif

    User.c

    #include "User.h"
    //初始化的方法
    User * userInit(int age)
    {
        User* user = (User*)malloc(sizeof(User));
        user->age = age;
        user->sayHi = sayHi;
        user->intP = int_P;
        user->testF1 = testF1;
        user->freeUser = freeUser;
    
        return user;
    }
    
    
    void int_P(int* intP) {
        printf("I am int_P..
    ");
    
    
    }
    
    void testF1(void * voidP)
    {
        printf("I am testF1...
    ");
    }
    
    
    
    void sayHi(int i)
    {
        printf("I am sayHi..
    ");
    }
    //释放User的方法
    void freeUser(void ** userPP)
    {
        free(*userPP);
        *userPP = NULL;
    }

    main.c  中进行测试

    #ifndef USER_H
        #include"User.h"
    #endif
    #ifndef _INC_STDIO
        #include<stdio.h>
    #endif
    int main() {
        int* p = NULL;
        void* p2 = NULL;
        User* user = userInit(12);
        User** userPP = &user;
        user->sayHi(1);
        user->intP(p);
        user->testF1(p2);
        printf("user 的地址是:%p
    ", user);
        printf("age 的值是:%d
    ",user->age);
        user->freeUser(userPP);//释放user内存的第一种方法
        /*
            释放user内存的第二种方法
            free(user);
            user = NULL;
            经过实践 目前来说更建议用“第二种方法”,因为更方便
        */
    
        printf("user 的地址是:%p
    ",user);
        
    
    
    
    
    
        getchar();
        return 1;
    }

    | 升级了上一个例子中的释放对象的方法

    User.h

    #pragma once
    #ifndef USER_H
        #define USER_H
    //*************************** 导包 ********************************
    #ifndef _INC_STDLIB
        #include<stdlib.h>
    #endif
    #ifndef _INC_STDIO
        #include<stdio.h>
    #endif
    
    //************************** 数据类型声明 *********************************
    /*
        问题思考:
            1. 看能否将初始化的方法也放到结构体中
    
        目标:
            1. 研究释放结构体变量的方法
    */
    typedef struct userS {
        int age;
        struct userS** userPP;
        void(*freeUser)(struct userS**);
    
    }User;
    
    User* userInit(int age);
    void freeUser(User** userPP);
    
    
    //***********************************************************
    #endif

    User.c

    #include"User.h"
    User* userInit(int age) {
        User* user = (User*)malloc(sizeof(User));
        printf("创建user对象的方法...
    ");
        user->age = age;
        user->freeUser = freeUser;
        //user->userPP = &user;//    这个值(user->userPP)在这里初始化方法外面是没有值的,暂时还没有想明白
        //printf("userInit方法中*userPP的地址:%p
    ", *user->userPP);
        return user;
    }
    void freeUser(User** userPP) {
        printf("释放User内存的方法...
    ");
        free(*userPP);
        *userPP = NULL;
    }

    main.c 中进行测试

    #ifndef USER_H
        #include"User.h"
    #endif
    
    #ifndef _INC_STDIO
    #include"stdio.h"
    #endif
    
    int main() {
    
        User* user = userInit(1);//1. 创建对象
        user->freeUser(user->userPP = &user);//2. 释放对象
        getchar();
        return 0;
    }

    | 结构体中指向结构体本身的指针定义说明

    |来看一个比较简单的版本

    main.c

    #include<stdio.h>
    
    
    typedef struct user{
        char* name;
        int age;
        void(*toString)(struct user);
        char* (*getUserName)(struct user);
    }User;
    void toString(User user);
    char* getUserName(User user);
    User User_(char* name,int age) {
        User user;
        user.name = name;
        user.age = age;
        user.toString = toString;
        user.getUserName = getUserName;
        return user;
    }
    void toString(User user) {
        printf("User[name:%s,age:%d]
    ",user.name,user.age);
    }
    char* getUserName(User user) {
        return user.name;
    }
    
    int main() {
        char name[] = "张三";
        User user = User_(name,12);
        user.toString(user);
        char* username = user.getUserName(user);
        printf("username is:%s
    ",username);
    
    
    
    
    
    
        getchar();
        return 1;
    }
    Fist day
  • 相关阅读:
    C++ 4种强制类型转换
    HTTP与HTTPS异同/HTTP1.0与HTTP1.1差别
    大数据处理-Trie树
    Linux进程状态转换图
    纯css实现背景图片半透明内容不透明的方法-opacity属性正确使用
    由vue理解passive修饰符引起的思考
    Vue+VSCode开发环境配置备忘(代码格式设置)
    哎呦喂web 前端三日老师 《精通Flex布局》
    flex实战之移动页面确定按钮置底布局
    Poptip插件拖动造成IOS下与同页面下mescroll.js也被拖动的解决,即对e.preventDefault();的理解
  • 原文地址:https://www.cnblogs.com/NULL-ROOT/p/10426850.html
Copyright © 2020-2023  润新知