继承和多态是面向对象语言最强大的功能。有了继承和多态,我们可以完成代码重用。在
C
中有许多技巧可以实现多态。本文的目的就是演示一
种简单和容易的技术,在
C
中应用继承和多态。通过创建一个
VTable
(
virtual table
)和在基类和派生类对象之间提供正确的访问,我们能在
C
中实现继承和多态。
VTable
能通过维护一张函数表指针表来实现。为了提供基类和派生类对象之间的访问,我们可以在基类中维护派生类的引用
和在派生类中维护基类的引用。
2
、说明
在
C
中实现继承和多态之前,我们应该知道类(
Class
)在
C
中如何表示。
2.1
、类在
C
中的表示
考虑
C++
中的一个类
“Person”
。
//Person.h
class Person
{
private:
char
* pFirstName;
char
* pLastName;
public:
Person(
const
char
* pFirstName,
const
char
* pLastName);
//constructor
~Person();
//destructor
void
displayInfo();
void
writeToFile(
const
char
* pFileName);
};
在
C
中表示上面的类,我们可以使用结构体,并用操作结构体的函数表示成员函数。
//Person.h
typedef
struct
_Person
{
char
* pFirstName;
char
* pLastName;
}Person;
new_Person(
const
char
*
const
pFirstName,
const
char
*
const
pLastName);
//constructor
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()
将设置函数指针值以指向合适的函数。这个函数指针表将作为对象访问函数的接口。
下面我们重新定义
C
中实现类
Person
。
//Person.h
typedef
struct
_Person Person;
//declaration of pointers to functions
typedef
void
(fptrDisplayInfo)(Person);
typedef
void
(fptrWriteToFile)( Person,
const
char
*);
typedef
void
(fptrDelete)( Person )
//Note: In C all the members are by default public. We can achieve
//the data hiding (private members), but that method is tricky.
//For simplification of this article
// we are considering the data members //public only.
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()
函数作为构造函数,它返回新创建的结构体实例。它初始化函数指针接口去访问其它成员函数。这里要注意的一点是,我们仅仅定
义了那些允许公共访问的函数指针,并没有给定私有函数的接口。让我们看一下
new_Person()
函数或
C
中类
Person
的构造函数。
//Person.c
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->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;
}
创建完对象之后,我们能够访问它的数据成员和函数。
Person* pPersonObj = new_Person(”
Anjali
“, ”
Jaiswal
“);
//displaying person info
pPersonObj->Display(pPersonObj);
//writing person info in the persondata.txt file
pPersonObj->WriteToFile(pPersonObj, ”
persondata.txt
“);
//delete the person object
pPersonObj->Delete(pPersonObj);
pPersonObj = NULL;
注意:
不像
C++
,
在
C
中我们不能在函数中直接访问数据成员。
在
C++
中,
可以隐式通过
“this”
指针直接访问数据成员。
我们知道
C
中是没有
“this”
指针的,通过显示地传递对象给成员函数。在
C
中为了访问类的数据成员,我们需要把调用对象作为函数参数传递。上面的例子中,我们把调用
对象作为函数的第一个参数,通过这种方法,函数可以访问对象的数据成员。