天天看点

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

<a target="_blank" href="http://blog.csdn.net/chief1985/article/details/2008479">用C语言模拟面向对象编程(上)</a>

导读: 

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

  虽然我接触计算机已经有将近一年了,但一直以来我不愿意写技术方面的文档,因为所谓的“技术”就是照着做得东西, 即使可能遇到一些难题,到网上搜索一下就可以解决,不值得把网上长篇累牍的文档复制粘贴到这里来。即使是自己写,也是写些别人已经解决过的东西。所以不论是数学,还是计算机,在这里我没有写过那种简单搬运知识的文章。 

  但即使再纯粹的技术,弄得时间长了都会产生一些独特的想法和感受,记录这些想法可能不光对自己是有意义的。今天来写第一篇偏向技术的东西。 

  如何在C语言中用面向对象的思路写程序?这已经是很多人考虑过的问题了,而且实际上已经有人在用C语言实现一些面向对象的项目了,比如,在Linux下大名鼎鼎的图形界面GNOME,就是通过C语言模拟的面向对象特性来实现的。 

  在一本名叫《面向对象编程,C++和Java比较教程》的书中有一个抛砖引玉的例子,代码如下(见该书中文版第67页,其中注释块中是自己的评注): 

  /* SimulatedOO.c */ 

  #include 

  /* 基类型: */ 

  typedef struct 

  { 

  char * name; 

  int age; 

  } User; 

  /* 子类型: */ 

  User genericUser; 

  char ** listOfCourses; 

  int numCourses; 

  int whatYear; 

  } StudentUser; 

  /********************************************************* 

  * 这样, 在子类型 StudentUser 中就有一个基类 User 的结构体 

  * 变量, 并且在内存中 User 结构体占据 StudentUser 的开头部分, 

  * 这样,把一个指向 StudentUser 类型的指针强制类型转换到 User* 

  * 类型,就可以访问到 User 的相应区域,这样就实现了继承机制。 

  ********************************************************/ 

  /* 为基类型User定义的函数: */ 

  void setUserName( User* user,char aName[] ) { 

  user -&gt; name = malloc(strlen(aName)+1); /* 原文为 malloc( sizeof(strlen(aName)+1) ), 这是不正确的。*/

  strcpy(user-&gt;name,aName); 

  } 

  char * getUserName( User * user) { 

  printf("/nName of user: %s/n",user-&gt;name); 

  return user-&gt;name; 

  void setUserAge(User * user,int yy) { 

  user -&gt; age=yy; 

  int getUserAge( User * user ) { 

  printf("%s's age: %d/n",user-&gt;name,user-&gt;age); 

  return user-&gt; age; 

  /* 为基类型User定义的函数: */ 

  /************************************************** 

  * 这个函数在书中是用来展示多态行为的,不过这种实现多态的 

  * 方式并不是很好,并不能实现类似于C++或Java中多态的动态连 

  * 接机制。具体用法见主程序中注释为“多态行为” 那两行。 

  *************************************************/ 

  int isSenior( User * user ) { 

  if ( user-&gt;age &gt;70 ) return 1; 

  else return 0; 

  /* 为子类型 StudentUser 定义的函数: */ 

  void setListOfCourses( StudentUser* student,char* listCrs[],int nCourses) { 

  int i; 

  char ** temp; 

  student-&gt;numCourses = nCourses; 

  temp = malloc( nCourses * sizeof( char* )); 

  student-&gt;listOfCourses=temp; 

  for(i=0;i numCourses;i++) { 

  *temp = malloc( strlen( *listCrs )+1); 

  strcpy(*temp,*listCrs); 

  *temp++; 

  listCrs++; 

  void printListOfCourses( StudentUser * student ) { 

  temp = student-&gt;listOfCourses; 

  printf("/n%s's courses: /n",student-&gt;genericUser.name); 

  for(i=0;i numCourses;i++) 

  printf("%s/n",*(temp++)); 

  void setYear( StudentUser* student,int yy) { 

  student-&gt;whatYear=yy; 

  int getYear( StudentUser* student) { 

  return student-&gt;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", &amp;( trillian-&gt;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 { 

  Sub() : data(5) {} 

  int getData() const { 

  那么如果有一个Base 类型的指针指向了一个Sub类,通过这个指针调用getData()时将返回子类Sub中的data:初始值5。这样,如果有一个储存基类型指针的数组,但这些指针有的指向基类,有的指向子类,那么我就可以通过指针统一地调用 getData() 函数,依然能够得到正确的值。 

  怎么在C中也实现类似的功能呢? (待续) 

本文转自 

http://blog.csdn.net/chief1985/article/details/2008479

<a target="_blank" href="http://blog.blogwhy.com/tpfly/e_23482.html">http://blog.blogwhy.com/tpfly/e_23482.html</a>