天天看點

用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>