简体   繁体   中英

How to set methods visible only for classes derived on different class?

I'm creating little GUI for my OpenGL game. I've got two base classes Widget and Container . Widget class has methods like setPosition(x,y) , setSize(w,h) ,... These methods should be visible only for classes derived from Container .

Edit: I can do it with friend and wrapper methods, but I'd like to do it without wrappers.

In case the suggestion was not clear from the comment, you can consider creating an interface with that subset of the methods and use private inheritance in Widget . Then use a protected (a single operation) in Container that would obtain that private interface for classes derived from it:

struct Drawable {    // choose a better name
  virtual void setPosition( int x, int y );
  virtual void setSize( int w, int h );
  virtual ~Drawable() {}
};
class Widget : private Drawable {
   friend class Container;
};
class Container {
protected:
    Drawable& getDrawable( Widget& w ) { return w; };
};
class MyContainer : public Container {
   void changeSize( Widget & w ) {
      getDrawable(w).setSize(10,20);
   }
};

The main difference with the forwarding options is that this scales better with the number of functions and is more maintainable (no need to update N-forwarders, just the accessor to the proper interface).

From a high level design point of view, a Widget is not Drawable in general, it is only Drawable from the context of Widget or Container .

I'm afraid of writing this answer because it seems too obvious, but couldn't you just make setPosition(x,y) and setSize(w,h) members of Container ?

or if there's some sort of unknown complexity could you make a WidgetContainer as a base class and put those methods in that class?

In my opinion, this is one of those "what can I do that should make another programmer feel dirty when they do it wrong" sort of situations: it's not well handled by the language, so you don't want to be overly restrictive in your code, because that tends to make things confusing. Friend-container-delegate setups will, in my opinion, just confuse people trying to figure out your code in everyday "how does this work" situations. You want to make it harder to abuse your code in "I need to hack on this" situations.

What I would do is perhaps something as simple as document well and call the (public) functions _setPosition and _setSize . The underscore will (hopefully) make other programmers go, "wha???" and read your documentation - which will explain exactly why it's a very bad idea for non- Container s to call those functions.

It's slightly ugly, but that's the point . I would certainly feel dirty calling rect._setPosition without understanding what's going on. It's a psychological solution, but used a lot in other languages where the access protection facilities are lacking - like Javascript - so is not so unusual as to be hideously ugly. Or at least, not more hideously ugly than trying to specify your requirements in the features of the language :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM