理解了指標以及函式指標,我們再來談談多態,就能更容易理解了,多態的直白意思即,一樣的事不同做法;相同名稱的方法,或是說介面,藉由給他不同的參數,就會做不一樣的事。比如人的跑是用兩條腿跑,狗的跑是用四條腿跑,同樣的"跑",執行的過程結果是不一樣的。
「多型是指向函式的指標」的一種應用,函式指標只是一個軀殼,放入不同的靈魂,則執行不同的結果,軀殼可以抽換不同的靈魂。
多態範例先拿Linux的FILE結構為例,Linux對於裝置都是看作是檔案,為了統一介面,Linux制定了以下操作檔案的介面。5個function pointer,本質上是5個inteface,需要實體function來填充它;本質上是5個軀殼,需要靈魂來填入。
struct FILE { void (*open)(char* name, int mode); void (*close)(); int (*read)(); void (*write)(char); void (*seek)(long index, int mode); };
前面幾行是實體function(靈魂),接下來指標(軀殼)放入function的位址,在最後一行程式碼。
#include "file.h" void open(char* name, int mode) {/*...*/} void close() {/*...*/}; int read() {int c;/*...*/ return c;} void write(char c) {/*...*/} void seek(long index, int mode) {/*...*/} struct FILE console = {open, close, read, write, seek};
仿效上述提到的Linux FILE struct, 建立struct PointOps,裡頭放函式指標void (*display)(struct Point*);再把此結構指標放進struct Point裡,這兩層可以都算是介面,一個是行為的群組,一個是display的軀殼。
point.c
#include "point.h" #include <stdlib.h> #include <math.h> struct PointOps { void (*display)(struct Point*); }; struct Point { double x,y; PointOps* ops; }; struct NamedPoint { struct Point point; void* priv; };
下面程式碼先看到最後6行,先建立了兩個display的實現function,function的位址再放進struct PointOps的結構中,function位址就是靈魂,這樣會在記憶體中劃開兩個function的空間,靈魂放到建立的結構實體中。再將這實體結構的位址,賦值給malloc出來的point實體物件中的ops,其就是用來存指標的指標變數。
struct Point* makepoint(double x, double y) { struct Point* p = malloc(sizeof(struct Point)); p->x = x; p->y = y; p->ops = &ops_point; return p; } struct NamedPoint* makeNamedPoint(double x, double y, char* name) { struct NamedPoint* p = malloc(sizeof(struct NamedPoint)); p->point.x = x; p->point.y = y; p->priv = malloc(sizeof(struct NamedPointPriv)); strcpy((p->priv)->name, name); p->point.ops = &ops_NamedPoint; return p; } static void do_displayPoint(struct Point* point) { ... } static void do_displayNamedPoint(struct Point* point) { ... } static PointOps ops_point = {do_displayPoint}; static PointOps ops_NamedPoint = {do_displayNamedPoint};
在調用point物件的時候,因為介面已經統一,只要調用一樣的介面,不同的物件,就會調用在創建物件時,所指定的最後實作函式(靈魂)
void displayPoint(struct Point* point) { point->ops->display(point); }
0 意見:
張貼留言