Home > Blockchain >  Why a Widget class uses pointers as data members?
Why a Widget class uses pointers as data members?

Time:09-17

I'm working through "Programming Principles and Practice", and I don't understand why this Widget class uses pointers as data members.

The book's explanations is this:

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?)

So, I still don't understand why the Widget can't have a named object Window win as a data member, which can take a different value when it's associated with a different Window. Could someone explain this a bit?

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
};

CodePudding user response:

Window own;

This will copy the whole Window object. If the real window changes, this widget will have an old and useless copy.

Window & own;

A reference. We meet two issues:

  • A) We can not know if the window has been deleted outside the widget code
  • B) The window must exists before this widget

 Window * own;

A pointer can be NULL, as opposed to a reference. This avoids reference issues.

The book seems a bit old, just because it uses raw-pointers.

EDIT due to comments
It is absolutely true that issue "A)" is the same for references and pointers. But it can be easier handled with a pointer.
What I wanted to point to is that when a window is deleted, the widget must be informed about it, so as to not use the "own" object.
With a pointer, it can be resetted to NULL, so any further attemp to use "own" can be easily catched. But with a reference you need, at least, an extra bool in your code just to store if "own" is valid or not.

CodePudding user response:

First, we need to work out the logical and implementation details. On the logical side, a window contains widgets: just like a mother has children. This is a one to many relationship. Each widget has an implementation entity, in this case an Fl_widget. It could equally be a MS windows Window, a QtWidget or and X-Windows Widget. It is one of those implementation dependent things

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

Within window itself, there will also be an implementation detail like another Fl_Widget or Fl_window.

The reason why we cannot have Window win instead of Window win* is because the window owns the widget and not the other way round. If we had Window win then whenever any window property changed, you'd have to modify all the widgets containing the same window. Taking, the mother child relationship, if the mother had a haircut, the mother member for all the children of the same mother would have to have a haircut. You'd have to have a method to keep track of and update all the mothers of all the children. This would just be a maintenance nightmare.

If we just hold a pointer to the window then we know that if the window is modified, all sibling widgets will be able to query the change in the parent window and get the same answer without a lot of effort.

The second part of your question about moving widgets between windows - I've never seen anyone do that. In all the implementations I have ever used, this is impossible. The parent window owns the widget for life. To "move it", you'd normally have to reincarnate it i.e. destroy it from the current window and re-create it in the new window.

  • Related