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
原文地址:https://www.cnblogs.com/NULL-ROOT/p/10426850.html