为什么 Widget class 使用指针作为数据成员?

Why a Widget class uses pointers as data members?

我正在研究“编程原理与实践”,我不明白为什么这个Widgetclass使用指针作为数据成员。

书中的解释是这样的:

Note that our Widget keeps track of its FLTK widget and the Window with which it is associated. Note that we need pointers for that because a Widget can be associated with different Windows during its life. A reference or a named object wouldn’t suffice. (Why not?)

所以,我仍然不明白为什么 Widget 不能将命名对象 Window win 作为数据成员,当它与不同的 Window。有人可以解释一下吗?

class Widget {
   // Widget is a handle to a Fl_widget — it is *not* a Fl_widget
   // we try to keep our interface classes at arm’s length from 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
   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;   // each Widget defines at least one action for a window

   Point loc;
   int width;
   int height;
   string label;
   Callback do_it;

protected:
   Window* own;       // every Widget belongs to a Window
   Fl_Widget* pw;     // a Widget “knows” its Fl_Widget
};
Window own;

这将复制整个 Window 对象。如果真正的 window 发生变化,这个小部件将有一个旧的无用的副本。

Window & own;

一个参考。我们遇到两个问题:

  • A) 我们无法知道window 是否在widget 代码外被删除
  • B) window 必须在此小部件
  • 之前存在

 Window * own;

与引用相反,指针可以为 NULL。这避免了引用问题。

这本书看起来有点旧,只是因为它使用了原始指针。

编辑 由于评论
问题“A)”对于引用和指针来说是相同的,这是绝对正确的。但是用指针可以更容易地处理它。
我想指出的是,当一个window被删除时,widget必须被告知它,以免使用“自己的”对象。
使用指针,可以将其重置为 NULL,因此可以轻松捕获任何进一步使用“own”的尝试。但是对于引用,您至少需要在代码中添加一个额外的 bool 来存储“own”是否有效。

首先,我们需要制定逻辑和实施细节。在逻辑方面,window 包含小部件:就像母亲有 children 一样。这是一对多的关系。每个小部件都有一个实现实体,在本例中为 Fl_widget。它同样可以是 MS windows Window、QtWidget 或 X-Windows Widget。它是那些依赖于实现的东西之一

 ___________
|window     |
|  _______  |     _________
| |widget-|-|--->|Fl_widget|
|  _______  |     _________
| |widget-|-|--->|Fl_widget|
|___________|

在 window 本身中,也会有一个类似于另一个 Fl_Widget 或 Fl_window 的实现细节。

为什么我们不能Window赢而不是Window* 是因为 window 拥有小部件,而不是相反。如果我们有 Window win 那么每当任何 window 属性 发生变化时,您都必须修改所有包含相同 [=39= 的小部件].以母child关系为例,如果母亲剪了头发,同一个母亲的所有child人的母亲成员都要剪头发。您必须有一种方法来跟踪和更新所有 children 的所有母亲。这将只是一场维护噩梦。

如果我们只持有指向 window 的指针,那么我们知道如果 window 被修改,所有同级小部件将能够查询 parent window 并且不费吹灰之力就得到了相同的答案。

关于在 windows 之间移动小部件的问题的第二部分 - 我从未见过有人这样做。在我曾经使用过的所有实现中,这是不可能的。 parent window 终生拥有该小部件。要“移动它”,您通常必须重新生成它,即从当前的 window 和 re-create 中销毁它到新的 window.