我正在學習《編程原理與實踐》,我不明白為什么這個Widget類使用指標作為資料成員。
書中的解釋是這樣的:
注意,我們的Widget會跟蹤它的FLTK widget和它所關聯的Window。請注意,我們需要指標,因為一個Widget在其生命周期中可以與不同的Windows關聯。一個參考或一個命名的物件是不夠的。(為什么不呢?)
所以,我仍然不明白為什么Widget不能有一個命名物件Window win作為資料成員,當它與不同的Window關聯時,它可以采取不同的值。誰能解釋一下這個問題呢?
class Widget {
//Widget是一個Fl_widget的句柄 - 它*不是*Fl_widget。
//我們試圖讓我們的介面類與FLTK保持一定距離。
public。
Widget(Point xy, int w, int h, const string& s, Callback cb)
: loc(xy), width(w), height(h)。label(s), do_it(cb) { }
virtual ~Widget() { } //destructor[/span]。
virtual void move(int dx, int dy)
{ hide(); pw->position(loc.x =dx, loc.y =dy); show(); }
virtual void hide() { pw-> hide(); }
virtual void show(){ pw-> show(); }
virtual void attach(Window& )= 0; //每個Widget都為一個視窗定義了至少一個動作。
點定位。
int 寬度。
int height;
字串標簽。
回呼do_it。
protected:
Window* own; //每個Widget都屬于一個Window。
Fl_Widget* pw; //一個Widget "知道 "它的Fl_Widget。
};
uj5u.com熱心網友回復:
Window own;
這將復制整個視窗物件。如果真正的視窗改變了,這個小部件將有一個舊的和無用的副本。
Window & own;
一個參考。我們遇到兩個問題:
- A) 我們無法知道視窗是否已經在部件代碼之外被洗掉
- B) 視窗必須是在部件代碼之外被洗掉。
- B) 視窗必須在這個小組件之前存在 。
Window * own;
一個指標可以是NULL,而不是參考。這就避免了參考問題。
這本書似乎有點舊,只是因為它使用了原始指標。
編輯由于評論的原因
問題 "A) "對于參考和指標來說是絕對正確的。但是用指標可以更容易的處理。
我想指出的是,當一個視窗被洗掉時,小部件必須被告知此事,以便不使用 "自己的 "物件。
用一個指標,它可以被重置為NULL,所以任何進一步使用 "自己的 "物件的嘗試都可以被輕易地抓住。但是對于參考,你至少需要在你的代碼中增加一個bool來存盤 "own "是否有效。
uj5u.com熱心網友回復:
首先,我們需要解決邏輯和實作的細節問題。 在邏輯方面,一個視窗包含部件:就像一個母親有孩子一樣。 這是一種一對多的關系。 每個widget都有一個實作物體,在本例中是Fl_widget。 它也可以是一個MS Windows視窗,一個QtWidget或X-Windows Widget。 它是那些依賴于實作的東西之一
。 ___________
|window |
| _______ | _________
|widget-|-|-->|Fl_widget|
| _______ | _________
|widget-|-|-->|Fl_widget|
|___________|
在視窗本身中,也會有一個實作細節,如另一個Fl_Widget或Fl_window。
我們之所以不能用Window win代替Window win*,是因為視窗擁有小部件,而不是相反。 如果我們有Window win,那么每當任何視窗屬性發生變化時,你就必須修改所有包含同一視窗的部件。 就拿母子關系來說,如果母親剪了頭發,那么同一母親的所有孩子的母親成員也必須剪頭發。 你必須要有一個方法來跟蹤和更新所有孩子的母親。 這將是一個維護的噩夢。
如果我們只是持有一個指向視窗的指標,那么我們知道,如果該視窗被修改,所有的兄弟姐妹部件將能夠查詢父視窗中的變化,并且不費吹灰之力就能獲得相同的答案。
您問題的第二部分關于在視窗之間移動部件 - 我從未見過有人這樣做。 在我曾經使用過的所有實作中,這是不可能的。 父視窗終生擁有該部件。 要想 "移動它",你通常必須將它轉世,即從當前視窗中銷毀它并在新視窗中重新創建它。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/315451.html
標籤:
