Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

OOP in C - Virtual Function (Chinese Version)

2,853 views

Published on

OOP in C - Virtual Function (Chinese Version)

  1. 1. OOP in C Virtual Function elpam.tw@gmail.com elpam@Taiwan, Taipei, 2008
  2. 2. LICENSE ● 本投影片授權方式為: – 姓名標示─非商業性─相同方式分享 3.0  台灣版 – http://creativecommons.org/licenses/by­nc­sa/3.0/tw/ ● 所有的範例程式皆為 Public Domain     elpam.tw@gmail.com
  3. 3. About This Slides ● All example was build by  – GCC­4.1.3 – GLIB­1.2.10 – GMAKE­3.81     elpam.tw@gmail.com
  4. 4. 請先覆習一下 Function Pointer 的使用方式     elpam.tw@gmail.com
  5. 5. Function Pointer /* 2­1.c */ typedef void (*FP) ( void ); void hello() { printf("hello "); } int main() { void world() { printf("worldn"); }   #> ./2­1 FP fp = hello;  hello world  fp();   #> fp = world; fp(); };     elpam.tw@gmail.com
  6. 6. Function Pointer (cont') /* 2­2.c */ ● 也可以當參數使用 typedef void (*FP) ( void ); #define ERROR 1 void error_test( FP callback ) { if( ERROR ){ callback(); } }   #> ./2­2 int main()   error happened  {   #> void error() { printf("error happenedn"); }        error_test( error ); };     elpam.tw@gmail.com
  7. 7. Function Pointer & Structure /* 2­3.c */ typedef void (*FP) ( void* ); ● 以 Function Pointer  struct A{         int a;               int b; 的方式實作 Member          FP  method; }; Function void a_real_method( void* p) {         struct A* this = p;         printf("%d,%dn",this­>a,this­>b); } int main() {   #> ./2­3         struct A a;   1,2         a.a = 1;        a.b = 2;   #>         a.method  = a_real_method;         a.method ( &a ); };     elpam.tw@gmail.com
  8. 8. Using Previous Slide to Implement Inherit 2­4.c ● 方便閱讀,加上一點 ' 命名規則 ' – 其實是龜毛的 Rule ● PREFIX_init – 該物件的 建構子 (Constructor) ● PREFIX_method – 該物件的 成員函式 (member function)     elpam.tw@gmail.com
  9. 9. Member Function's Inherit (1) struct A { void A_real_method_a( void* p) { int a; struct A* this = p; FP  method_a; printf("this is method_a %dn",this­>a);  }; } struct B { void B_real_method_b( void* p) { struct A parent; struct B* this = p; int b; printf("this is method_b %dn",this­>b);  FP  method_b; } }; int main()  { void a_init( struct A* a)  { struct B b; a ­> a = 1; a_init( &b );    a ­> method_a = A_real_method_a;        b_init( &b ); } void b_init( struct B* b)  { struct A* ap = &b; b ­> b = 2; b ­> method_b = B_real_method_b; ap ­> method_a( ap ); } b  .  method_b( &b ); };     elpam.tw@gmail.com
  10. 10. Member Function's Inherit (2) /* 2­4.c */ int main() ● Child 如果希望執行 ( 存取 )  { struct B b; Parent 的函式 ( 變數 ) ,需要 a_init( &b );    先 Cast 成 Parent 再執行 ( 存        b_init( &b ); 取) struct A* ap = &b; ap ­> method_a( ap ); b  .  method_b( &b ); };   #> ./2­4   this is method_a 1   this is method_b 2       #> elpam.tw@gmail.com
  11. 11. 結論 ● 我們可以實作 class_init() 時將 class 內的 member value and member function 都設定好 – 也就是 ''Constructor''  ● 自已實作 C 不提供的 Member Function!!     elpam.tw@gmail.com
  12. 12. Implement Virtual Function 2­5.c ● Child 的 init 可以將 Parent 的 Member Function 做改寫的動作,以達到 Virtual Function 的效果 – 下一頁粉紅色的那一行     elpam.tw@gmail.com
  13. 13. Virtual Function (1) void A_real_method_a( void* p)  { struct A* this = p; printf("this is %s %dn"                          ,__FUNCTION__,this­>a);  void A_init( struct A* a) } { void B_real_method_a( void* p)  a ­> a = 1; { a ­> method_a = A_real_method_a; struct B* this = p; } printf("this is %s %dn"                           ,__FUNCTION__,this­>b);  } void B_init( struct B* b) void B_real_method_b( void* p)  { { struct A* a = b; struct B* this = p; b ­> b = 2; printf("this is %s %dn" a ­> method_a = B_real_method_a;                            ,__FUNCTION__,this­>b);  b ­> method_b = B_real_method_b; } }     elpam.tw@gmail.com
  14. 14. Virtual Function (2) ● A_init 一定要比 B_init 先執行 – Parent 的 Constructor 需要先執 行 /* 2­5.c */ int main() { struct B b;   #> ./2­5 A_init( &b ); this is A_real_method_a 1 this is B_real_method_a 2 struct A* ap = &b; this is B_real_method_b 2 ap ­> method_a( ap );   #> B_init( &b ); ap ­> method_a( ap ); b  .  method_b( &b ); };     elpam.tw@gmail.com
  15. 15. Constructor's Wrapper 2­6.c     elpam.tw@gmail.com
  16. 16. Constructor in C (1) ● we use PREFIX_new to replace malloc – 所有的物件都以 PREFIX_NEW 產生,以確保 Constructor 被正確的執行 struct A{ struct A* A_new()    int a; {    int b;    struct A* ret = malloc( sizeof(A) ); };    ret ­> a = 0;    ret ­> b = 1;    return ret; }     elpam.tw@gmail.com
  17. 17. Constructor in C (2) ● 以前面的例子 /* 2­6.c */ /* 2­6.c */ int main() struct B* B_new() { {         struct B* pb = B_new();    struct B* pb = malloc( sizeof(B) );    struct A* pa = pb;         ((struct A*)pb) ­> method_a( pb );    A_init( pa );         pb ­> method_b( pb );    B_init( pb );    return pb; }; }     elpam.tw@gmail.com
  18. 18. Constructor in C (3) ● 繼承關係越復雜時, PREFIX_new 很難去維護 – 請試想三層繼承時,開發者希望在第一及第二層之間 再加上一層物件 ● 所以我們需要更有效率的方式來撰寫 Constructor – GObject 提供了一個有效率的方式     elpam.tw@gmail.com
  19. 19. Conclusion ● 以上的 Tips 提供了一種方式來撰寫 Object­ Oriented 的程式 – 可自行練習 :) ● 相較於 C++ 的繼承,此種方式所撰寫出來的物 件為靜態形別,所有的 Offset 都是 Compiler  Time 已決定好的,所以不會有繼承濫用的問題 – 執行效率 ● 但是如果不正確的使用,依舊會造成程式碼難以   閱讀,也容易產生 BUG  elpam.tw@gmail.com

×