原创 以C語言觀點理解C++的this指標/指針

2007-3-7 11:11 3020 7 7 分类: 软件与OS

我常用低階的語言觀點來看高階語言,我覺得那樣可以更深入的了解使用法方,堪至可以模擬出是如何實做的,可能遇到的問題。能想像Bjarne Stroustrup這個創造人當初可能是怎麼想的嗎?


這篇文章最主要的目的是要解釋為何需要用this指標?


前言:想像一下在沒有class之前,C語言程式設計師是如何達成近class模組化功能? 曾看過一些使用C開發的遊戲程式,裡面總定義了一堆的struct,當然還有一堆和這struct有關的function。在cpp裡struct和class是同樣的,都可以定義資料成員(data member)、成員函式(member function/method),僅差別在struct預設成員是public。然而在C語言裡,struct是不能有成員函式定義的,也因此C程式人員可能獨立的把方法寫在Global區塊上,是否可能模擬出把方法也嵌入struct中呢? 這樣就很像class了…請看以下我寫的演示範本:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef
struct StudentInfo
{
  char *mName;
  int   mAgeInAc;
  int   mAgeInTw;
  void  (*mpCalc)(struct StudentInfo *self);
  int   (*mpGetTwAge)(struct StudentInfo *slef);
  void  (*mCopy)(struct StudentInfo *slef,
                              struct StudentInfo *src);


}STI;


/* 私人的方法 */
void ac_to_tw(STI *self)
{
  self->mAgeInTw = self->mAgeInAc - 1911;
}


/*公開的方法*/
int get_tw_age(STI *self)
{
  self->mpCalc(self);
  return self->mAgeInTw;
}


/*公開的方法*/
void copy(STI *self, STI *src)
{
  *self = *src;
}


/*建構子*/
STI create_sti_object(void)
{
  STI object;
  object.mName = 0;
  object.mpCalc = ac_to_tw;
  object.mpGetTwAge = get_tw_age;
  object.mCopy = copy;
  return object;
}


/*動態建構子*/
STI *p_create_sti_object(void)
{
  STI *p_object = (STI *) calloc(1,sizeof(STI));
  p_object->mName = 0;
  p_object->mpCalc = ac_to_tw;
  p_object->mpGetTwAge = get_tw_age;
  p_object->mCopy = copy;
  return p_object;
}


/*動態解構子*/
void destroy_sti_object(STI *self)
{
  free(self);
}


#pragma argsused
int main(int argc, char* argv[])
{
  int my_tw_age;
  STI student_info;
  STI *p_student_info;
  STI my_info;
  STI babe_info;
  STI copy_info;


  /*沒有建構式的建立法*/
  student_info.mName = "蕭一世";
  student_info.mAgeInAc = 1951;
  student_info.mpCalc = ac_to_tw;
  student_info.mpCalc(&student_info);
  printf("%s 民國%d年生\n",student_info.mName,student_info.mAgeInTw);


  /*使用動態建構方式,且直接呼叫私人方法*/
  p_student_info = p_create_sti_object();
  p_student_info->mName = "蕭二世";
  p_student_info->mAgeInAc = 1961;
  p_student_info->mpCalc(p_student_info);
  printf("%s 民國%d年生\n",p_student_info->mName,p_student_info->mAgeInTw);
  destroy_sti_object(p_student_info);


  /*使用建構子,且呼叫公開方法取回值,Instance1 */
  my_info = create_sti_object();
  my_info.mName = "蕭沖";
  my_info.mAgeInAc = 1971;
  my_tw_age = my_info.mpGetTwAge(&my_info);
  printf("%s 民國%d年生\n",my_info.mName,my_tw_age);


  /*使用建構子,且呼叫公開方法取回值,Instance2A */
  babe_info = create_sti_object();
  babe_info.mName = "寶貝";
  babe_info.mAgeInAc = 1976;
  my_tw_age = babe_info.mpGetTwAge(&babe_info);
  printf("%s 民國%d年生\n",babe_info.mName,my_tw_age);


  /*使用拷備函式,Instance2B */
  copy_info = create_sti_object();
  copy_info.mCopy(& copy_info, &babe_info);
  copy_info.mName = "寶貝拷備";
  copy_info.mAgeInAc = copy_info.mAgeInAc + 7;
  my_tw_age = copy_info.mpGetTwAge(& copy_info);
  printf("%s 民國%d年生\n",copy_info.mName,my_tw_age);


  system("pause");


  return 0;
}


我們使用了函式指標來實作「方法」的部份。值得注意的部份是:從這裡我們可以看出方法的部份是共享的,僅資料的部份是各自不同(參考最後二個instance)。使用建構式是為了要把方法與Global下的function連結起來,這也是cpp中的一個新觀念-「建構子」。但在這裡還沒有實作出public與private的限制,也就是data hiding的部份。上面的方法中,都有一個參數STI *self這就是為何cpp中的method需要*this的原因了!只是cpp中把這個參數給隱藏起來,在complie時在偷偷的插入這個pointer到最前面的參數,並在method中關於data member和member function的部份加上this->,就如同上面的範例使用了self->。這樣就可以達成「Instance的方法共享,資料私有」。free後method的部份依舊存在。僅data被free了!


範例子寫了一個copy method,演示了cpp中何時你可能會把this這個關鍵字用出來,當實作copy時,你就要自己寫入 *this 這就不是compiler會幫你的了! 還有另一個可能會用到的時候: 傳回物件的reference時return *this,不過這是在reference type 是cpp裡才有的。


 

文章评论0条评论)

登录后参与讨论
我要评论
0
7
关闭 站长推荐上一条 /2 下一条