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;
}
运行结果
以上代码中最后一个释放函数存在问题,待解决!!!