在C语言里进行面向对象设计--模拟运行时识别

本文介绍了一种在C语言中实现类似C++运行时类型识别的方法,通过使用虚函数表,并针对不同类的对象进行识别。这种方法不仅节省了内存,还增加了设计的灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    面向对象的另一个特性是运行时识别。当然,如果你的系统设计的足够完美的话,也用不到什么运行时识别,但是有时使用一下运行是识别,能够是设计简化不少。言归正传,本文就是在前文的基础上再研究一下,如何使用 C 来进行运行时识别。

 

我们知道, C++ 里的虚函数实际上不是与对象绑定,而是与类绑定的。也就是说,一个类一个虚函数表,而不是一个对象一个虚函数表。所以,如果一个类的虚函数较多时,像前文那样定义接口:

struct IStream

{

           void (*write)(IStream* pStream, char* pstr);

         void(*read)(IStream* pStream, char buf, ssize_t size);

         void (*flush)(IStream* pStream);

         …

};

就会很浪费,因为每个对象都有 sizeof(struct IStream) 这么大。但是我们知道,虚函数表是与类绑定的,而不是与对象绑定的,那么我们可以改进这个设计。

struct IStreamClass

{

           void (*write)(IStream* pStream, char* pstr);

         void(*read)(IStream* pStream, char buf, ssize_t size);

         void (*flush)(IStream* pStream);

         …

};

 

基类的定义改为:

        struct IStream{

        {

             struct IStreamClass* vtbl;

        }

 

如果需要实现一个 FileStream 的话,可以定义一个具体类。

        struct FileStream

       {

            struct IStream base;

            FILE* f;

        }

  FileStreamClass 可以使用一个全局变量来定义:

        extern struct IStreamClass class_FileStream;

 

因为这个虚函数表是与类绑定的,所以有了它,我们还可以增加运行时识别的功能!

        int isFileStream(struct IStream* pStream){

           return pStream->vtbl == class_FileStream;

        }

 

这样设计还能够增加集成层次。比如 FileStream 本身又定义了一个虚函数 vFunc ,有一个类 AFileStream 继承自 FileStream ,则可以在 FileStream.h 中增加这样的定义:

***FileStream.h***

       struct FileStreamClass{

           struct IStream stream_class;

           void (*vFunc)();

       }

       extern FileStreamClass class_FileStream;

 

***FileStream.c***

      FileStreamClass class_FileStream = {

         {

             FileStream_write,

             FileStream_read,

             FileStream_flush

             …

         },

          FileStream_vFunc

      };

 

AFileStream 的定义为下面这样。

***AFileStream.h***

Struct AFileStream{

    struct FileStreamClass* vtbl;

    …

};

extern FileStreamClass class_AFileStream;

AFileStream.c 的内容就不用写了。

这样以来,你仍然可以用 FileStream->vtbl 当做 struct IStream 使用。

这个运行时识别的设计不支持动态创建的功能。 C++ 的动态创建功能, MFC 的设计就算是很好的了,但是那个需要构造函数的自动调用功能, C 里面没有这种功能。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值