用C语言模拟面向对象编程(上)

用C语言模拟面向对象编程(上)

导读: 

  用C语言模拟面向对象编程 

  虽然我接触计算机已经有将近一年了,但一直以来我不愿意写技术方面的文档,因为所谓的“技术”就是照着做得东西, 即使可能遇到一些难题,到网上搜索一下就可以解决,不值得把网上长篇累牍的文档复制粘贴到这里来。即使是自己写,也是写些别人已经解决过的东西。所以不论是数学,还是计算机,在这里我没有写过那种简单搬运知识的文章。 
  但即使再纯粹的技术,弄得时间长了都会产生一些独特的想法和感受,记录这些想法可能不光对自己是有意义的。今天来写第一篇偏向技术的东西。 
  如何在C语言中用面向对象的思路写程序?这已经是很多人考虑过的问题了,而且实际上已经有人在用C语言实现一些面向对象的项目了,比如,在Linux下大名鼎鼎的图形界面GNOME,就是通过C语言模拟的面向对象特性来实现的。 
  在一本名叫《面向对象编程,C++和Java比较教程》的书中有一个抛砖引玉的例子,代码如下(见该书中文版第67页,其中注释块中是自己的评注): 
  /* SimulatedOO.c */ 
  #include 
  #include 
  #include 
  /* 基类型: */ 
  typedef struct 
  { 
  char * name; 
  int age; 
  } User; 
  /* 子类型: */ 
  typedef struct 
  { 
  User genericUser; 
  char ** listOfCourses; 
  int numCourses; 
  int whatYear; 
  } StudentUser; 
  /********************************************************* 
  * 这样, 在子类型 StudentUser 中就有一个基类 User 的结构体 
  * 变量, 并且在内存中 User 结构体占据 StudentUser 的开头部分, 
  * 这样,把一个指向 StudentUser 类型的指针强制类型转换到 User* 
  * 类型,就可以访问到 User 的相应区域,这样就实现了继承机制。 
  ********************************************************/ 
  /* 为基类型User定义的函数: */ 
  void setUserName( User* user,char aName[] ) { 
  user -> name = malloc(strlen(aName)+1); /* 原文为 malloc( sizeof(strlen(aName)+1) ), 这是不正确的。*/
  strcpy(user->name,aName); 
  } 
  /* 为基类型User定义的函数: */ 
  char * getUserName( User * user) { 
  printf("/nName of user: %s/n",user->name); 
  return user->name; 
  } 
  /* 为基类型User定义的函数: */ 
  void setUserAge(User * user,int yy) { 
  user -> age=yy; 
  } 
  /* 为基类型User定义的函数: */ 
  int getUserAge( User * user ) { 
  printf("%s's age: %d/n",user->name,user->age); 
  return user-> age; 
  } 
  /* 为基类型User定义的函数: */ 
  /************************************************** 
  * 这个函数在书中是用来展示多态行为的,不过这种实现多态的 
  * 方式并不是很好,并不能实现类似于C++或Java中多态的动态连 
  * 接机制。具体用法见主程序中注释为“多态行为” 那两行。 
  *************************************************/ 
  int isSenior( User * user ) { 
  if ( user->age >70 ) return 1; 
  else return 0; 
  } 
  /* 为子类型 StudentUser 定义的函数: */ 
  void setListOfCourses( StudentUser* student,char* listCrs[],int nCourses) { 
  int i; 
  char ** temp; 
  student->numCourses = nCourses; 
  temp = malloc( nCourses * sizeof( char* )); 
  student->listOfCourses=temp; 
  for(i=0;i numCourses;i++) { 
  *temp = malloc( strlen( *listCrs )+1); 
  strcpy(*temp,*listCrs); 
  *temp++; 
  listCrs++; 
  } 
  } 
  /* 为子类型 StudentUser 定义的函数: */ 
  void printListOfCourses( StudentUser * student ) { 
  int i; 
  char ** temp; 
  temp = student->listOfCourses; 
  printf("/n%s's courses: /n",student->genericUser.name); 
  for(i=0;i numCourses;i++) 
  printf("%s/n",*(temp++)); 
  } 
  /* 为子类型 StudentUser 定义的函数: */ 
  void setYear( StudentUser* student,int yy) { 
  student->whatYear=yy; 
  } 
  /* 为子类型 StudentUser 定义的函数: */ 
  int getYear( StudentUser* student) { 
  return student->whatYear; 
  } 
  int main() 
  { 
  User * zaphod; 
  StudentUser* trillian; 
  char * listCourses[]={"Physics","Chemistry","algebra"}; 
  int numCrs = sizeof(listCourses)/sizeof(listCourses[0]); 
  zaphod = malloc(sizeof(User)); 
  setUserName(zaphod,"Zaphod"); 
  setUserAge(zaphod,89); 
  getUserName(zaphod); 
  getUserAge(zaphod); 
  trillian=malloc(sizeof(StudentUser)); 
  setUserName((User*)trillian,"Trillian" ); 
  setUserAge((User*)trillian,18); 
  getUserName((User*)trillian); 
  getUserAge((User*)trillian); 
  setListOfCourses(trillian,listCourses,numCrs); 
  printListOfCourses(trillian); 
  /*  多态行为 */ 
  printf("/nZaphod is senior is %s/n",isSenior(zaphod)? "true":"false"); 
  printf("/nTrillian is senior is %s/n", isSenior((User*)trillian)? "true":"false"); 
  /***************************************************** 
  * 和setUserAge 、setUserName之类的函数一样,isSenior 
  * 需要一个基类指针参数,通过将 trillian 转换为 User* 
  * 类型,就会把指向trillian 中User域的指针传进函数。 
  * ***************************************************/ 
  printf("name field of trillian is at address: %p/n", &( trillian->genericUser.name )); 
  printf("trillian when cast to User* is at address: %p/n",(User*)trillian ); 
  /*************************************************** 
  * 这两行输出的地址值是一样的。 
  * *************************************************/ 
  } 
  在C++和Java中,多态行为是由一种动态连接机实现的,比如,在C++中定义如下的类 Base 和它的子类 Sub: 
  class Base { 
  int data; 
  public: 
  Base() : data(3) {} 
  virtual int getData() const { 
  return data; 
  } 
  }; 
  class Sub:public Base { 
  int data; 
  public: 
  Sub() : data(5) {} 
  int getData() const { 
  return data; 
  } 
  }; 
  那么如果有一个Base 类型的指针指向了一个Sub类,通过这个指针调用getData()时将返回子类Sub中的data:初始值5。这样,如果有一个储存基类型指针的数组,但这些指针有的指向基类,有的指向子类,那么我就可以通过指针统一地调用 getData() 函数,依然能够得到正确的值。 
  怎么在C中也实现类似的功能呢? (待续) 

本文转自 

http://blog.csdn.net/chief1985/article/details/2008479
http://blog.blogwhy.com/tpfly/e_23482.html

时间: 2024-11-05 21:55:55

用C语言模拟面向对象编程(上)的相关文章

我所偏爱的 C 语言面向对象编程范式

我所偏爱的 C 语言面向对象编程范式 面向对象编程不是银弹.大部分场合,我对面向对象的使用非常谨慎,能不用则不用.相关的讨论就不展开了. 但是,某些场合下,采用面向对象的确是比较好的方案.比如 UI 框架,又比如 3d 渲染引擎中的场景管理.C 语言对面向对象编程并没有原生支持,但没有原生支持并不等于不适合用 C 写面向对象程序.反而,我们对具体实现方式有更多的选择. 大部分用 C 写面向对象程序的程序员受 C++ 影响颇深.企图用宏模拟出一个常见 C++ 编译器已经实现的对象模型.于我愚见,这

Javascript面向对象编程

Javascript是一门很灵活的语言,允许我们模拟面向对象编程中的很多机机制.在JS中充分使用面向对象设计思想,可以极大限度的提升代码重用.降低模块间的偶合.更好的逻辑分层与并行开发.下面分几个步骤简单谈下我的理解. 一.数据类型与包装类 包装类 -- 类型名 -- 常见值 -- 分类 Number -- number -- 123.123 -- 基本数据类型 Boolean -- Boolean -- true.false -- 基本数据类型 String -- string -- "hel

Python回顾与整理11:面向对象编程

0.说明         阅读一些优秀的Python源代码,会发现面向对象编程的思想无处不在,其实对于任何一门面向对象编程语言来说,面向对象编程都是极其重要的,因此,掌握好一门语言的面向对象编程,将有助于进行更高级的开发.(本文来自香飘叶子51cto博客<Python回顾与整理>系列博文专题) 1.引言 (1)类与实例 类         在Python中有新式类和经典类之分,无非就是有没有显式地继承一个父类: 1 2 3 4 5 6 7 # 新式类 class MyNewObjectType

013_《Delphi面向对象编程思想》

<Delphi面向对象编程思想> Delphi 教程 系列书籍 (013) <Delphi面向对象编程思想> 网友(邦)整理 EMail: shuaihj@163.com 下载地址: Pdf 作者: 刘艺 [作译者介绍] 丛书名: Borland核心技术丛书 出版社:机械工业出版社 ISBN:7111127722 上架时间:2003-10-10 出版日期:2003 年9月 开本:16开 页码:476 版次:1-1 内容简介 这是一本纯粹讨论dlephi面向对象编程的力作. 本书以精

PHP中实现面向对象编程(上)

编程|对象 这篇文章介绍在PHP的面向对象编程(OOP).我将演示如何用面向对象的概念编出较少的代码但更好的程序.祝大家好运. 面向对象编程的概念对每一个作者来说都有不同的看法,我提醒一下一个面向对象语言应有的东西: - 数据抽象和信息隐藏 - 继承 - 多态性 在PHP中使用类进行封装的办法: class Something { // In OOP classes are usually named starting with a cap letter. var $x; function se

java语言学习002_面向对象编程思想

      人类在认识世界时,为了方便自己和智慧提升,很自然的对事物进行了分类.对世界进行了抽象,若把所有各个事物看做对象,纵观所有对象,这些对象具有各自的或共有的特征,并且又有共有的或各自的的能力,这样就可以对具有相同一些特征和一些能力的事物进行了归类.       比如,车,有汽车,火车他们都有哪些属性?                  汽车,特征:长度,颜色,速度,轮胎,载重,平面行走--能力:移动,载东西,--                  火车,特征:长度,颜色,速度,轮胎,载重

《面向对象设计实践指南:Ruby语言描述》—第1章 1.4节 面向对象编程简介

1.4 面向对象编程简介 面向对象设计实践指南:Ruby语言描述 面向对象的应用程序由对象和它们之间传递的消息构成.其中,消息相对更为重要.但在本节的简介里(以及在本书的前面几个章节里),这两个概念都同等重要. 1.4.1 过程式语言 相对于非面向对象(或过程式)的编程来说,面向对象编程是面向对象的.依据这两种风格的差异来考虑它们很有意义.假设有这么一种通用的编程语言,它可用来创建简单的脚本.在这门语言里,你可以定义变量(即组成多个名称),并将这些名字与少量的数据相关联.一旦进行了分配,便可以通

F#探险之旅(四):面向对象编程(上)

面向对象编程概述(OOP) 面向对象编程是当今最流行的编程范式,看看TIOBE 2008年9月的编程语言排行榜就很清楚了: 在这些主流语言中,除了C,都或多或少地提供对OOP的支持,而Java和C#更是纯粹的面向对象编程语言,C还有一个子集--Objective-C.值得一提的是Delphi的强势回归.下图则是各个编程范式的占有率: OOP编程范式是指使用"对象"及"对象"之间的交互来设计应用程序.OOP的基本概念包括类,对象,实例,方法,消息传递,继承,抽象,封装

PHP面向对象编程详解:类和对象

PHP面向对象编程详解:类和对象 从OOP的视角看,不应区分语言.无论是C++.无论是Java.无论是.net还有更多面向对象的语言,只要你了解了OO的真谛,便可以跨越语言,让你的思想轻松的跳跃.便没有对于Java..net.PHP 之间谁强谁弱的争执了. 希望这个介绍PHP5面向对象编程(OOP)的资料能让初学者受益,能让更多的PHPer开始转向OO的编程过程. 相对PHP4,PHP5在面向对象方面改变了很多.我们将只介绍PHP5环境下的面向对象.而我们必须改变自己来跟随PHP5的发展.如果代