我正在为我的OpenGL游戏创建小GUI。我有两个基类Widget
和Container
。 Widget
类包含setPosition(x,y)
,setSize(w,h)
等方法,这些方法仅对从Container
派生的类可见。
编辑:我可以使用朋友和包装器方法来完成它,但我想在没有包装器的情况下这样做。
答案 0 :(得分:2)
如果评论中未明确提出建议,您可以考虑使用该方法子集创建接口,并在Widget
中使用私有继承。然后在Container
中使用受保护的(单个操作)来获取从它派生的类的私有接口:
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);
}
};
与转发选项的主要区别在于,它可以根据功能的数量进行更好的扩展,并且更易于维护(无需更新N转发器,只需更新适当的接口)。
从高级设计的角度来看,Widget
一般不是Drawable
,而Drawable
或{{1}的上下文只有Widget
}。
答案 1 :(得分:1)
我害怕写这个答案,因为它看起来太明显了,但你不能只是setPosition(x,y)
成员setSize(w,h)
和Container
成员吗?
或者如果存在某种未知的复杂性,您可以将WidgetContainer
作为基类并将这些方法放在该类中吗?
答案 2 :(得分:1)
在我看来,这是“我能做些什么才能让另一个程序员在做错的时候感觉很脏”的情况之一:这种情况并没有得到很好的处理,所以你不想成为你的代码过于严格,因为这会让事情变得混乱。在我看来,朋友 - 容器代表设置只会让那些试图在日常“如何工作”情况下找出代码的人感到困惑。您希望在“我需要破解这种情况”的情况下更难滥用您的代码。
我要做的事情可能就像文档一样简单,并调用(公共)函数_setPosition
和_setSize
。下划线(希望)会让其他程序员去,“哇???”并阅读你的文档 - 这将解释为什么非Container
调用这些函数是一个非常糟糕的主意。
它有点难看,但那是点。如果不了解正在发生的事情,我肯定会感到肮脏地打电话rect._setPosition
。这是一种心理解决方案,但在其他缺乏访问保护功能的语言中使用了很多 - 比如Javascript - 所以不是那么不寻常的丑陋。或者至少,并不比试图在语言的功能中指定您的要求更丑陋:)