用C语言模仿C++的类

本文参考以下作者文章文章
来自:吴秦 - 博客园
作者:吴秦
链接:http://www.cnblogs.com/skynet/archive/2010/09/23/1833217.html

继承和多态是面向对象语言最强大的功能。有了继承和多态,我们可以完成代码重用。在C中有许多技巧可以实现多态。本文的目的就是演示一种简单和容易的技术,在C中应用继承和多态。通过创建一个VTable(virtual table)和在基类和派生类对象之间提供正确的访问,我们能在C中实现继承和多态。VTable能通过维护一张函数表指针表来实现。为了提供基类和派生类对象之间的访问,我们可以在基类中维护派生类的引用和在派生类中维护基类的引用

在C中实现继承和多态之前,我们应该知道类(Class)在C中如何表示。

代码如下

//person.h
#ifndef PERSON_H
#define PERSON_H
typedef struct _Person Person;
typedef void (*fptrDisplayInfo)(Person*);
typedef void (*fptrWriteToFile)(Person*);
typedef void (*fptrDelete)(Person*);

typedef struct _Person
{
    void* pDerivedObj;//指向派生类
    char* pFirstName;
    char* pLastName;
    fptrDisplayInfo DisplayInfo;
    fptrWriteToFile WriteToFile;
    fptrDelete Delete;
}Person;
Person* new_Person(const char* const pFirstName, const char* const pLastName);
void delete_Person(Person* const pPersonObj);
void Person_DisplayInfo(Person* const pPersonObj);
void Person_WriteToFile(Person* const pPersonObj, const char* const pFileName);
#endif // PERSON_H

//person.c
#include"person.h"
#include"stdio.h"
Person* new_Person(const char* const pFirstName, const char* const pLastName)
{
    Person* pObj = NULL;
    //allocating memory
    pObj = (Person*)malloc(sizeof(Person));
    if (pObj == NULL)
    {
        return NULL;
    }

    pObj->pDerivedObj = pObj;//指向自己

    pObj->pFirstName = malloc(sizeof(char)*(strlen(pFirstName)+1));
    if (pObj->pFirstName == NULL)
    {
        return NULL;
    }
    strcpy(pObj->pFirstName, pFirstName);

    pObj->pLastName = malloc(sizeof(char)*(strlen(pLastName)+1));
    if (pObj->pLastName == NULL)
    {
        return NULL;
    }
    strcpy(pObj->pLastName, pLastName);

    //Initializing interface for access to functions
    pObj->Delete = delete_Person;
    pObj->DisplayInfo = Person_DisplayInfo;
    pObj->WriteToFile = Person_WriteToFile;

    return pObj;
}

void delete_Person(Person* const pPersonObj)
{

}
void Person_DisplayInfo(Person* const pPersonObj)
{

}
void Person_WriteToFile(Person* const pPersonObj, const char* const pFileName)
{

}

//employee.h
#ifndef EMPLOYEE_H
#define EMPLOYEE_H

#include "person.h"
typedef struct _Employee Employee;
typedef struct _Employee
{
    Person* pBaseObj;//指向基类
    char* pDepartment;
    char* pCompany;
    int nSalary;

}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 Employee_WriteToFile(Person* const pPersonObj,const char* const pFileName);


#endif // EMPLOYEE_H

//employee.c
#include"employee.h"
#include<stdio.h>
Person* new_Employee(const char* const pFirstName, const char* const pLastName,
                     const char* const pDepartment, const char* const pCompany, int nSalary)
{
    Employee* pEmpObj;
    //calling base class construtor
    Person* pObj = new_Person(pFirstName, pLastName);
    //allocating memory
    pEmpObj = malloc(sizeof(Employee));
    if (pEmpObj == NULL)
    {
        pObj->Delete(pObj);
        return NULL;
    }
    pObj->pDerivedObj = pEmpObj; //pointing to derived object
    pEmpObj->pBaseObj = pObj;
    //initialising derived class members
    pEmpObj->pDepartment = malloc(sizeof(char)*(strlen(pDepartment)+1));
    if(pEmpObj->pDepartment == NULL)
    {
        return NULL;
    }
    strcpy(pEmpObj->pDepartment, pDepartment);
    pEmpObj->pCompany = malloc(sizeof(char)*(strlen(pCompany)+1));
    if(pEmpObj->pCompany== NULL)
    {
        return NULL;
    }
    strcpy(pEmpObj->pCompany, pCompany);
    pEmpObj->nSalary = nSalary;
    
    //Changing base class interface to access derived class functions
    //virtual destructor
    //person destructor pointing to destrutor of employee
    pObj->Delete = delete_Employee;
    pObj->DisplayInfo = Employee_DisplayInfo;
    pObj->WriteToFile = Employee_WriteToFile;
    
    return pObj;
}

void delete_Employee(Person* const pPersonObj)
{
    
}

void Employee_DisplayInfo(Person* const pPersonObj)
{
    
}
void Employee_WriteToFile(Person* const pPersonObj,const char* const pFileName)
{
    
}

//main.c
#include <stdio.h>
#include "employee.h"
int main(int argc, char *argv[])
{
    Person* PersonObj = new_Person("Anjali", "Jaiswal");
    Employee* EmployeeObj = new_Employee("Gauri", "Jaiswal","HR", "TCS", 40000);

    //accessing person object

    //displaying person info
    PersonObj->DisplayInfo(PersonObj);
    //writing person info in the persondata.txt file
//    PersonObj->WriteToFile(PersonObj,"persondata.txt");
    //calling destructor
    PersonObj->Delete(PersonObj);

    //accessing to employee object

    //displaying employee info
    //通过基类调用基类函数指针指向的派生类的函数
    EmployeeObj->pBaseObj->DisplayInfo(EmployeeObj);
    //writing empolyee info in the employeedata.txt file
//    EmployeeObj->WriteToFile(EmployeeObj, "employeedata.txt");
    //calling destrutor
    EmployeeObj->pBaseObj->Delete(EmployeeObj);
    printf("%d",EmployeeObj->nSalary);
    return 0;
}

在这里插入图片描述
结论

使用上面描述的简单的额外代码能是过程式C语言有多态和继承的特性。我们简单的使用函数指针创建一个VTable和在基类和派生类对象中交叉维护引用。用这些简单的步骤,我们在C中可以实现继承和多态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值