c语言实现类
1、类在C中的表示
在C++中的创建一个类"Person"。
//Person.h class Person { private: char* pFirstName; char* pLastName; public: Person(constchar* pFirstName, constchar* pLastName); //constructor ~Person(); //destructorvoid displayInfo(); void writeToFile(constchar* pFileName); }; |
//Person.h
typedef struct _Person { char* pFirstName; char* pLastName; }Person;void new_Person(const char* const pFirstName, const char* const pLastName); //constructorvoid 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()将设置函数指针值以指向合适的函数。这个函数指针表将作为对象访问函数的接口。
2. 下面我们重新定义C中实现类Person。
//Person.h
typedef struct _Person Person; //declaration of pointers to functions typedef void (*fptrDisplayInfo)(Person*); typedef void (*fptrWriteToFile)( Person*, constchar*); typedef void (*fptrDelete)( Person *) ; typedef struct _Person { char* pFName; char* pLName; //interface for function fptrDisplayInfo Display; fptrWriteToFile WriteToFile; fptrDelete Delete; }Person; Person* new_Person(const char* const pFirstName, const char* const pLastName); //constructor void delete_Person(Person* const pPersonObj); //destructor void Person_DisplayInfo(Person* const pPersonObj); void Person_WriteToFile(Person* const pPersonObj, const char* pFileName); |
这里要注意的一点是,我们仅仅定义了那些允许公共访问的函数指针,并没有给定私有函数的接口。
让我们看一下new_Person()函数或C中类Person的构造函数。
//Person.c person* new_Person(constchar* const pFirstName, constchar* const pLastName) { Person* pObj = NULL; //allocating memory pObj = (Person*)malloc(sizeof(Person)); if (pObj == NULL) { return NULL; } 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->Display = Person_DisplayInfo; pObj->WriteToFile = Person_WriteToFile; return pObj; } |
void
delete_Person(Person* const pPersonObj)
{
printf("call Person_DisplayInfo()\n");
free(pPersonObj);
}
|
void Person_DisplayInfo(Person* const pPersonObj)
{
printf("call Person_DisplayInfo()\n");
printf("pFirstName:%s pLastName:%s\n",pPersonObj->pFirstName,pPersonObj->pLastName);
}
|
void Person_WriteToFile(Person* const pPersonObj, const char* pFileName)
{
printf("call Person_WriteToFile()\n");
}
|
main()
{
Person*
pPersonObj = new_Person("pengdan", "farsight");
pPersonObj->Display(pPersonObj);
pPersonObj->WriteToFile(pPersonObj, "persondata.txt");
pPersonObj->Delete(pPersonObj);
pPersonObj
= NULL;
}
|
Person类的表示——检查初始化接口指向成员函数:
继承-Employee类继承自Person类:
在上面的例子中,类Employee继承类Person的属性。因为DisplayInfo()和WriteToFile()函数是virtual的,
我们能够从Person的实例访问Employee对象中的同名函数。为了实现这个,我们创建Person实例的时候也初始化Employee类。
多态使这成为可能。 在多态的情况下,去解析函数调用,C++使用VTable——即一张函数指针表。
前面我们在结构体中维护的指向函数的指针接口的作用类似于VTable。
//Polymorphism in C++ Person PersonObj("pengdan", "farsight"); Employee EmployeeObj("kouxiaojuan", "liuyan", "HR", "TCS", 40000); Person* ptrPersonObj = NULL; //preson pointer pointing to person object ptrPersonObj = &PersonObj; //displaying person info ptrPersonObj ->Display(); //writing person info in the persondata.txt file ptrPersonObj ->WriteToFile("persondata.txt"); //preson pointer pointing to employee object ptrPersonObj = &EmployeeObj; //displaying employee info ptrPersonObj ->Display(); //writing empolyee info in the employeedata.txt file ptrPersonObj ->WriteToFile("employeedata.txt"); |
在C中,继承可以通过在派生类对象中维护一个基类对象的引用来完成。在基类实例的帮助下,women可以访问基类的数据成员和函数。然而,为了实现多态,基类对象应该能够访问派生类对象的数据。为了实现这个,基类应该有访问派生类的数据成员的权限。
为了实现虚函数,派生类的函数签名应该和基类的函数指针类似。即派生类函数将以基类对象的一个实例为参数。我们在基类中维护一个派生类的引用。在函数实现上,我们可以从派生类的引用访问实际派生类的数据。
C中的继承-Person和Employee结构体:
如图所示,我们在基类结构体中声明了一个指针保存派生类对像,并在派生类结构体中声明一个指针保存基类对象。
在基类对象中,函数指针指向自己的虚函数。在派生类对象的构造函数中,我们需要使基类的接口指向派生类的成员函数。这使我们可以通过基类对象(多态)灵活的调用派生类函数。更多细节,请检查Person和Employee对象的构造函数。
当我们讨论C++中的多态时,有一个对象销毁的问题。为了正确的清楚对象,它使用虚析构函数。在C中,这可以通过使基类的删除函数指针指向派生类的析构函数。派生类的析构函数清楚派生类的数据和基类的数据和对象。注意:检查例子的源码中,实现须构造函数和虚函数的实现细节。
//Person.h
typedef struct _Person Person; //pointers to function typedef void (*fptrDisplayInfo)(Person*); typedef void (*fptrWriteToFile)(Person*, const char*); typedef void (*fptrDelete)(Person*) ; typedefstruct _person { void* pDerivedObj; char* pFirstName; char* pLastName; fptrDisplayInfo Display; fptrWriteToFile WriteToFile; fptrDelete Delete; }person; Person* new_Person(constchar* const pFristName, constchar* const pLastName); //constructor void delete_Person(Person* const pPersonObj); //destructor void Person_DisplayInfo(Person* const pPersonObj); void Person_WriteToFile(Person* const pPersonObj, constchar* const pFileName); //Person.c//construction of Person object Person* new_Person(constchar* const pFirstName, constchar* const pLastName) { Person* pObj = NULL; //allocating memory pObj = (Person*)malloc(sizeof(Person)); if (pObj == NULL) { return NULL; } //pointing to itself as we are creating base class object 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//destructor pointing to destrutor of itself pObj->Delete = delete_Person; pObj->Display = Person_DisplayInfo; pObj->WriteToFile = Person_WriteToFile; return pObj; } |
void
delete_Person(Person* const pPersonObj)
{
printf("call Person_DisplayInfo()\n");
free(pPersonObj);
}
|
void Person_DisplayInfo(Person* const pPersonObj)
{
printf("call Person_DisplayInfo()\n");
printf("pFirstName:%s pLastName:%s\n",pPersonObj->pFirstName,pPersonObj->pLastName);
}
|
void Person_WriteToFile(Person* const pPersonObj, const char* pFileName)
{
printf("call Person_WriteToFile()\n");
}
|
//Employee.h #include "Person.h" typedef struct _Employee Employee; typedefstruct _Employee { Person* pBaseObj; char* pDepartment; char* pCompany; int nSalary; //If there is any employee specific functions; add interface here. }Employee; Person* new_Employee(const char* const pFirstName, const char* const pLastName, const char* const pDepartment, const char* const pCompany, int nSalary); //constructor void delete_Employee(Person* const pPersonObj); //destructor void Employee_DisplayInfo(Person* const pPersonObj); void Employee_WriteToFile(Person* const pPersonObj, const char* const pFileName); //Employee.c 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; 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; pObj->Delete = delete_Employee;
pObj->Display = Employee_DisplayInfo;
pObj->WriteToFile = Employee_WriteToFile;
return pObj;
}
|
main() { Person* PersonObj = new_Person("pengdan", "farsight"); } |
通过以上例子,我们看到使用c语言也可以实现封装、继承、多态,学习好以上知识会有助于我们更好的学习面向对象的语言。
static struct platform_driver driver={
.probe = hello_probe,
.driver.name = "fs4412-beep",
.remove = hello_remove,
};
|