在C语言里进行面向对象设计:模拟运行时识别
来源:优易学  2011-12-10 16:52:11   【优易学:中国教育考试门户网】   资料下载   IT书店
  面向对象的另一个特性是运行时识别。当然,如果你的系统设计的足够完美的话,也用不到什么运行时识别,但是有时使用一下运行是识别,能够是设计简化不少。言归正传,本文就是在前文的基础上再研究一下,如何使用 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 里面没有这种功能。

责任编辑:小草

文章搜索:
 相关文章
热点资讯
资讯快报
热门课程培训