2014-04-08 91 views
3

目前我正在閱讀Stroustrup Programming:Principles and Practice C++。我面對這個例子:遞歸函數指針。 Stroustrup的例子

typedef void (*Pfct0)(struct Shape2*); 
typedef void (*Pfct1int)(struct Shape2*,int); 

struct Shape2{ 
    Pfct0 draw; 
    Pfct1int rotate; 
}; 

void draw(struct Shape2* p) 
{ 
    (p->draw)(p); 
} 

void rotate(struct Shape2* p,int d) 
{ 
    (p->rotate)(p,d); 
} 

int f(struct Shape2* pp) 
{ 
    draw(pp); 
    return 0; 
} 

我不能得到什麼函數繪製和旋轉實際上做。 我知道什麼是typedef,函數指針, - >運算符。 據我瞭解,p-> draw函數會自動遞歸調用。我對嗎? 做繪畫或旋轉等功能有什麼實際用途?

+3

不,他們不是自動遞歸地調用它們。他們調用結構的繪製和旋轉字段中包含的函數。 – George

+3

這裏沒有遞歸。非類函數只是通過指針調用類函數。 – EJP

+0

您能否指定在哪裏繪製或旋轉字段?我不明白。或者,也許你可以把一些參考樣本代碼,在那裏我可以閱讀有關類似的問題 – Qeeet

回答

1

功能drawrotate調用一個功能由結構p成員指出,並調用上的指針這些功能於該結構p

也許這將幫助:

typedef void (*pointer_to_function)(struct Shape2*); 

struct Shape2{ 
    pointer_to_function draw; 
    Pfct1int rotate; 
}; 

void function(struct Shape2* p) 
{ 
    (p->draw)(p); 
    ^^^^^^^^^ 
    // this is pointer_to_function so call the function pointed to by it 
    // with some argument of type struct Shape2*, in example p itself, why not 
} 

在這個片段中的誤導是,我們沒有看到如何在對象Shape2指針初始化,但之前必須初始化爲指向適當簽名的一些功能他們被傳遞到全球drawrotate

+0

因此,當創建一個Shape2對象時,必須爲它創建方法? – Qeeet

+1

是的,你不能取消引用未初始化的指針 – 4pie0

2

在我看來,Stroustrup在純C中實現了類似於對象的分派。每個Shape2對象都有自己的繪製和旋轉方法。給定一個任意的Shape2 p,draw(p)查找p的draw方法,並將其應用於自身(大概p將會有一些其他內容,draw將讀取並採取行動。)函數不會遞歸調用它自己,除非特定遞歸地繪製p調用的繪製函數。這非常類似於如果Shape2是基類,p.draw()將在C++中執行的操作。

1

Shape2的每個實例都可以有自己的繪製和旋轉功能。

如果s是一個指向Shape

draw(s); 

相同

(s->draw)(s); 

這可以被用來實現類似

drawrect(Shape* s); 
drawcircle(Shape* s); 
... 
Shape shapes[2]; 
shapes[0].draw = &drawrect; 
shapes[1].draw = &drawcircle; 
... 
for(int i = 0; i < 2; i++) { 
    draw(&shapes[i]); 
}