只要您稍加注意,您就可以在 C 中实现一种面向对象的编程。在我所做的方式中,我使用了函数指针以及以函数指针作为成员的结构。
例如,为了具有一种数据独立性,您可能有一个类似于快速排序 (qsort) 函数的函数,它为 data long 提供了一个指向对数据进行操作的函数的指针。通常使用这种方法,您最终会使用各种类型的 void 指针来允许使用指向任何数据类型的指针。
我使用的另一种方法是为各种类型的设备支持的常见操作提供一个抽象接口,然后创建一个为这些操作提供函数指针模板的结构。然后,我将创建一个由这些结构组成的数组,并通过使用指向为特定设备实现该操作的特定函数的函数指针填充数组元素。
例如,像这个非常简单的例子是我用来为几种不同设备提供标准接口的东西。该接口通过提供标准接口隐藏了设备差异。
// I create a struct that specifies what the function
// interface looks like for each of these operations for the
// devices that we are supporting.
typedef struct {
int (*pInput)(int iValue);
char *(*pName) (void);
int (*pDance) (int iTune, char *aszName);
} HardwareInterface;
// next I provide the function prototypes for the various devices.
// we have two different devices, Device_01 and Device_02 which
// have a common set of operations with the same interface.
int Device_01_Input (int iValue);
char *Device_01_Name (void);
int Device_01_Dance (int iTune, char *aszName);
int Device_02_Input (int iValue);
char *Device_02_Name (void);
int Device_02_Dance (int iTune, char *aszName);
// now I define my array of the device operation interfaces.
// this is where I provide the link between a specific operation
// on a specific device. I will number my devices beginning with
// zero to the number of devices supported minus one.
HardwareInterface HardwareList [] = {
{Device_01_Input, Device_01_Name, Device_01_Dance},
{Device_02_Input, Device_02_Name, Device_02_Dance},
};
在这一点上,我可以调用一个函数来获取我真正想要使用的设备。此函数返回硬件列表的索引。所以它可能会变成这样。
int DeviceStdInput (int iValue)
{
int i = GetDeviceType ();
return HardwareList[i].pInput (iValue);
}
或者我可以使用句柄方法,以便调用一个函数,该函数为传递给函数的某些描述中指定的设备提供句柄。然后对我的标准接口的任何调用都会指定句柄。在下面,句柄只是不同设备数组的索引。
{
int iHandle = GetDeviceHandle ("Device_01");
int iXvalue = DeviceStdInput (iHandle, iValue);
}
函数 DeviceStdInput() 看起来像:
int DeviceStdInput (int iHandle, int iValue)
{
return HardwareList[iHandle].pInput (iValue);
}
您仍然需要实现用于每个设备的实际功能,但是这提供了一种方法,可以为具有通用操作的多个设备提供标准接口,然后您可以在其余代码中使用标准接口。
我用它来提供一个标准的输出接口,其中输出设备是文件、打印机和 Web 服务。实际的接收器或输出设备由用户选择。使用接口的代码没有改变。只要界面没有改变,添加更多设备就很容易了。在某些情况下,我会拥有不支持特定操作的设备,并且该功能只会返回而无需执行任何操作。