Top Banner
OOP in C Virtual Function [email protected] elpam@Taiwan, Taipei, 2008
19

OOP in C - Virtual Function (Chinese Version)

May 19, 2015

Download

Documents

Kai-Feng Chou
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: OOP in C - Virtual Function (Chinese Version)

OOP in CVirtual Function

[email protected]@Taiwan, Taipei, 2008

Page 2: OOP in C - Virtual Function (Chinese Version)

   [email protected]

LICENSE

● 本投影片授權方式為:

– 姓名標示─非商業性─相同方式分享 3.0  台灣版

– http://creativecommons.org/licenses/by­nc­sa/3.0/tw/

● 所有的範例程式皆為 Public Domain

Page 3: OOP in C - Virtual Function (Chinese Version)

   [email protected]

About This Slides

● All example was build by – GCC­4.1.3– GLIB­1.2.10– GMAKE­3.81

Page 4: OOP in C - Virtual Function (Chinese Version)

   [email protected]

請先覆習一下 Function Pointer 的使用方式

Page 5: OOP in C - Virtual Function (Chinese Version)

   [email protected]

Function Pointer

/* 2­1.c */

typedef void (*FP) ( void );

void hello() { printf("hello "); }

int main(){

void world() { printf("world\n"); }

FP fp = hello;fp();fp = world;fp();

};

  #> ./2­1 hello world   #>

Page 6: OOP in C - Virtual Function (Chinese Version)

   [email protected]

Function Pointer (cont')

● 也可以當參數使用/* 2­2.c */typedef void (*FP) ( void );

#define ERROR 1

void error_test( FP callback ){

if( ERROR ){callback();

}}

int main(){

void error() { printf("error happened\n"); }       error_test( error );};

  #> ./2­2  error happened   #>

Page 7: OOP in C - Virtual Function (Chinese Version)

   [email protected]

Function Pointer & Structure

● 以 Function Pointer 的方式實作 Member Function

/* 2­3.c */typedef void (*FP) ( void* );struct A{        int a;               int b;        FP  method;};void a_real_method( void* p){        struct A* this = p;        printf("%d,%d\n",this­>a,this­>b);}int main(){        struct A a;        a.a = 1;        a.b = 2;        a.method  = a_real_method;        a.method ( &a );};

  #> ./2­3  1,2  #>

Page 8: OOP in C - Virtual Function (Chinese Version)

   [email protected]

Using Previous Slide to Implement Inherit

2­4.c● 方便閱讀,加上一點 ' 命名規則 '

– 其實是龜毛的 Rule

● PREFIX_init– 該物件的 建構子 (Constructor)

● PREFIX_method– 該物件的 成員函式 (member function)

Page 9: OOP in C - Virtual Function (Chinese Version)

   [email protected]

Member Function's Inherit (1)void A_real_method_a( void* p) {

struct A* this = p;printf("this is method_a %d\n",this­>a); 

}void B_real_method_b( void* p) {

struct B* this = p;printf("this is method_b %d\n",this­>b); 

}

void a_init( struct A* a)  {a ­> a = 1;a ­> method_a = A_real_method_a;

}void b_init( struct B* b)  {

b ­> b = 2;b ­> method_b = B_real_method_b;

}

struct A {int a;FP  method_a;

};struct B {

struct A parent;int b;FP  method_b;

};int main()  {

struct B b;a_init( &b );   

       b_init( &b );

struct A* ap = &b;

ap ­> method_a( ap );b  .  method_b( &b );

};

Page 10: OOP in C - Virtual Function (Chinese Version)

   [email protected]

Member Function's Inherit (2)

● Child 如果希望執行 ( 存取 ) Parent 的函式 ( 變數 ) ,需要先 Cast 成 Parent 再執行 ( 存取 )

/* 2­4.c */int main(){

struct B b;a_init( &b );   

       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

  #>

Page 11: OOP in C - Virtual Function (Chinese Version)

   [email protected]

結論

● 我們可以實作 class_init() 時將 class 內的member value and member function 都設定好

– 也就是 ''Constructor'' 

● 自已實作 C 不提供的 Member Function!!

Page 12: OOP in C - Virtual Function (Chinese Version)

   [email protected]

Implement Virtual Function

2­5.c● Child 的 init 可以將 Parent 的 Member Function

做改寫的動作,以達到 Virtual Function 的效果– 下一頁粉紅色的那一行

Page 13: OOP in C - Virtual Function (Chinese Version)

   [email protected]

Virtual Function (1)void A_real_method_a( void* p) {

struct A* this = p;printf("this is %s %d\n"

                         ,__FUNCTION__,this­>a); }void B_real_method_a( void* p) {

struct B* this = p;printf("this is %s %d\n"

                          ,__FUNCTION__,this­>b); }void B_real_method_b( void* p) {

struct B* this = p;printf("this is %s %d\n"

                           ,__FUNCTION__,this­>b); }

void A_init( struct A* a){

a ­> a = 1;a ­> method_a = A_real_method_a;

}

void B_init( struct B* b){

struct A* a = b;b ­> b = 2;a ­> method_a = B_real_method_a;b ­> method_b = B_real_method_b;

}

Page 14: OOP in C - Virtual Function (Chinese Version)

   [email protected]

Virtual Function (2)

● A_init 一定要比 B_init 先執行– Parent 的 Constructor 需要先執

行 /* 2­5.c */int main(){

struct B b;A_init( &b );

struct A* ap = &b;ap ­> method_a( ap );

B_init( &b );ap ­> method_a( ap );b  .  method_b( &b );

};

  #> ./2­5this is A_real_method_a 1this is B_real_method_a 2this is B_real_method_b 2  #>

Page 15: OOP in C - Virtual Function (Chinese Version)

   [email protected]

Constructor's Wrapper2­6.c

Page 16: OOP in C - Virtual Function (Chinese Version)

   [email protected]

Constructor in C (1)

● we use PREFIX_new to replace malloc– 所有的物件都以 PREFIX_NEW 產生,以確保

Constructor 被正確的執行

struct A{   int a;   int b;};

struct A* A_new(){   struct A* ret = malloc( sizeof(A) );   ret ­> a = 0;   ret ­> b = 1;   return ret;}

Page 17: OOP in C - Virtual Function (Chinese Version)

   [email protected]

Constructor in C (2)

● 以前面的例子

/* 2­6.c */int main(){        struct B* pb = B_new();

        ((struct A*)pb) ­> method_a( pb );        pb ­> method_b( pb );

};

/* 2­6.c */struct B* B_new(){   struct B* pb = malloc( sizeof(B) );   struct A* pa = pb;   A_init( pa );   B_init( pb );   return pb;}

Page 18: OOP in C - Virtual Function (Chinese Version)

   [email protected]

Constructor in C (3)

● 繼承關係越復雜時, PREFIX_new 很難去維護– 請試想三層繼承時,開發者希望在第一及第二層之間

再加上一層物件

● 所以我們需要更有效率的方式來撰寫Constructor– GObject 提供了一個有效率的方式

Page 19: OOP in C - Virtual Function (Chinese Version)

   [email protected]

Conclusion

● 以上的 Tips 提供了一種方式來撰寫 Object­Oriented 的程式

– 可自行練習 :)

● 相較於 C++ 的繼承,此種方式所撰寫出來的物件為靜態形別,所有的 Offset 都是 Compiler Time 已決定好的,所以不會有繼承濫用的問題

– 執行效率

● 但是如果不正確的使用,依舊會造成程式碼難以閱讀,也容易產生 BUG