#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; }