c语言实现继承和多态

c语言实现继承和多态

重点:
继承:模仿c++中vtable
多态:交叉组合引用

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

/*在c中实现继承和多态*/
//Person.h
//typedef struct _Person
//{
//	char* pFirstName;
//	char* pLastName;
//}Person;
/*构造函数声明*/

/*重新定义_Person 实现Person*/
/*实现一个vtable函数表*/
typedef struct _Person Person;/*相当于前向声明*/
typedef struct _Employee Employee;
typedef void (*fptrDisplayInfo)(Person*);
typedef void (*fptrWriteToFile)(Person*, const char*);
typedef void (*fptrDelete)(Person*);
typedef struct _Person
{

	char* pFName;
	char* pLName;
	fptrDisplayInfo Display;
	fptrWriteToFile WriteToFile;
	fptrDelete Delete;
	Employee* pDerivedObj;/*保存派生类对象*/
}Person;



Person* new_Person(const char* const pFirstName, const char* const pLastName);
void delete_Person(Person* const pPersonObj);//destructor
void Person_DisplayInfo(Person* const pPersonObj);
void Person_WriteToFile(Person* const pPersonObj, const char* const pFileName);

Person* new_Person(const char* const pFirstName, const char* const pLastName)
{
	printf("基类构造函数开始\n");
	Person* pObj = NULL;
	pObj = (Person*)malloc(sizeof(Person));
	if (NULL == pObj)
	{
		return NULL;
	}
	pObj->pDerivedObj = pObj;
	pObj->pFName = malloc(sizeof(char)*(strlen(pFirstName) + 1));
	memset(pObj->pFName, 0x00, sizeof(pObj->pFName));
	if (NULL == pObj->pFName)
	{
		return NULL;
	}
	strcpy(pObj->pFName, pFirstName);
	pObj->pLName = malloc(sizeof(char)*(strlen(pLastName) + 1));
	memset(pObj->pLName, 0x00, sizeof(pObj->pLName));
	if (NULL == pObj->pLName)
	{
		return NULL;
	}
	strcpy(pObj->pLName, pLastName);
	pObj->Delete = delete_Person;
	pObj->Display = Person_DisplayInfo;
	pObj->WriteToFile = Person_WriteToFile;
	printf("基类构造函数结束\n");
	return pObj;
}
void delete_Person(Person* const pPersonObj)
{
	printf("基类析构函数开始\n");
	if (pPersonObj->pFName != NULL)
	{
		free(pPersonObj->pFName);
		pPersonObj->pFName = NULL;
	}
	if (pPersonObj->pLName != NULL)
	{
		free(pPersonObj->pLName);
		pPersonObj->pLName = NULL;
	}
	printf("基类析构函数结束\n");
}
void Person_WriteToFile(Person* const pPersonObj, const char* const pFileName)
{
	printf("基类成员函数1开始\n");
	if (NULL == pPersonObj)
	{
		return;
	}
	FILE* fptr = fopen(pFileName, "wt");
	if (NULL == fptr)
	{
		return;
	}
	char buf[BUFSIZ];
	memset(buf, 0x00, sizeof(buf));
	sprintf(buf, "%s %s", pPersonObj->pFName, pPersonObj->pLName);
	fwrite(buf, sizeof(buf), 1, fptr);
	fclose(fptr);
	return;
}
void Person_DisplayInfo(Person* const pPersonObj)
{
	printf("基类成员函数2开始\n");
	if (NULL == pPersonObj)
	{
		return;
	}
	printf("My Name is %s %s\n", pPersonObj->pFName, pPersonObj->pLName);
	return;
}

/*多态的简单例子*/
/*创建Person的时候初始化Employee*/
/*在c中继承可以通过在派生类对象中维护一个基类对象的引用来完成
为了实现虚函数,派生类的函数签名应该和基类的函数指针类似,即派生类函数将以基类对象的一个实例为参数
在基类中维护一个派生类的引用,在函数实现上,可以从派生类的引用访问实际派生类的数据*/
void test01()
{
	/*创建完对象之后,能够访问它的数据成员和函数*/
	Person* pPerson = new_Person("yimao", "666");
	pPerson->Display(pPerson);
	pPerson->WriteToFile(pPerson, "1.txt");
	pPerson->Delete(pPerson);
	pPerson = NULL;

}
typedef struct _Employee
{
	Person* pBaseObj; /*维护基类对象的引用*/
	char* pDepartment;
	char* pCompany;
	int salary;
	/*需要使用基类的接口指向派生类的成员函数使基类对象(多态)灵活调用派生类函数*/
	/*析构:使基类的删除函数指针指向派生类的析构函数,派生类的析构函数清楚派生类的数据和基类的数据和对象
	*/
}Employee;
Person* new_Employee(const char* const pFirstName, const char* const pLastName, const char* const pDepartment, const char* const pCompany, int nSalary);
void delete_Employee(Person* const pPersonObj);
void Employee_DisplayInfo(Person* const pPersonObj);
void Emplyee_WriteToFile(Person* const pPersonObj, const char* const pFileName);
Person* new_Employee(const char* const pFirstName, const char* const pLastName, const char* const pDepartment, const char* const pCompany, int nSalary)
{
	printf("派生类构造函数开始\n");
	Employee* pEmpObj;
	Person* pObj = new_Person(pFirstName, pLastName);
	pEmpObj = malloc(sizeof(Employee));
	memset(pEmpObj, 0x00, sizeof(pEmpObj));
	if (NULL == pEmpObj)
	{
		pObj->Delete(pObj);
		return NULL;
	}
	pObj->pDerivedObj = pEmpObj;
	pEmpObj->pDepartment = malloc(sizeof(char)*strlen(pDepartment)+1);
	memset(pEmpObj->pDepartment, 0x00, sizeof(pEmpObj->pDepartment));
	if (NULL == pEmpObj->pDepartment)
	{
		return NULL;
	}
	strcpy(pEmpObj->pDepartment, pDepartment);
	pEmpObj->pCompany = malloc(sizeof(char)*strlen(pCompany)+1);
	memset(pEmpObj->pCompany, 0x00, sizeof(pEmpObj->pCompany));
	if (NULL == pEmpObj->pCompany)
	{
		return NULL;
	}
	strcpy(pEmpObj->pCompany, pCompany);
	pEmpObj->salary = nSalary;
	pObj->Delete = delete_Employee;
	pObj->Display = Employee_DisplayInfo;
	pObj->WriteToFile = Emplyee_WriteToFile;

	pObj->WriteToFile = Emplyee_WriteToFile;
	printf("派生类构造函数结束\n");
	return pObj;


}
void delete_Employee(Person* const pPersonObj)
{

	printf("派生类析构函数开始\n");
	if (NULL == pPersonObj)
	{
		return;
	}
	//Employee* pTmp = (Employee*)(pPersonObj->pDerivedObj);

	if (pPersonObj->pFName != NULL)
	{
		free(pPersonObj->pFName);
		pPersonObj->pFName = NULL;
	}
	if (pPersonObj->pLName != NULL)
	{
		free(pPersonObj->pLName);
		pPersonObj->pLName = NULL;
	}
	if (pPersonObj->pDerivedObj != NULL)
	{
	
			/*这里隐藏着一个问题:如果先释放pDepartment会报错debug error*/
			if (pPersonObj->pDerivedObj->pDepartment != NULL)
			{
				free(pPersonObj->pDerivedObj->pDepartment);
				pPersonObj->pDerivedObj->pDepartment = NULL;
			}
			if (pPersonObj->pDerivedObj->pCompany != NULL)
			{
				free(pPersonObj->pDerivedObj->pCompany);
				pPersonObj->pDerivedObj->pCompany = NULL;
			}

		free(pPersonObj->pDerivedObj);
		pPersonObj->pDerivedObj = NULL;
	}

	free(pPersonObj);
	printf("派生类析构函数结束\n");

}
void Employee_DisplayInfo(Person* const pPersonObj)
{
	printf("派生类成员函数1\n");
	printf("My Name is %s %s %s %s\n", pPersonObj->pFName, pPersonObj->pLName, pPersonObj->pDerivedObj->pDepartment, pPersonObj->pDerivedObj->pCompany);
}
void Emplyee_WriteToFile(Person* const pPersonObj, const char* const pFileName)
{
	printf("派生类成员函数2");
}
/*使用多态*/
void test02()
{
	Person* PersonObj = new_Person("yimao", "123");
	Person* EmployeeObj = new_Employee("ermao", "123", "HR", "TCS", 40000);
	PersonObj->Display(PersonObj);
	PersonObj->WriteToFile(PersonObj, "1.txt");

	PersonObj->Delete(PersonObj);
	EmployeeObj->WriteToFile(EmployeeObj, "employee.txt");
	EmployeeObj->Display(EmployeeObj);
	EmployeeObj->Delete(EmployeeObj);
}
int main()
{
	test02();


	system("pause");
	return EXIT_SUCCESS;
}

运行结果
在这里插入图片描述以上代码中最后一个释放函数存在问题,待解决!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值