我有一个Widget
类和一个CompositeWidget
来自它。 CompositeWidget
增加了儿童管理行为。 Widget
构造函数将CompositeWidget*
参数作为窗口小部件父级。我需要使用此父指针来访问CompositeWidget
中的某些功能。例如:
Widget::Widget(CompositeWidget* parent)
{
parent_->AddChild(*this);
}
这迫使我创建一个公共方法CompositeWidget::AddChild
。可以将此接口保持为类层次结构的私有(有点像反向 - protected
访问 - 仅限于基类)?在考虑这样的问题时,我是在做设计失礼吗?
编辑:我正在努力避免友谊(如果在这种情况下可行)。
答案 0 :(得分:3)
这迫使我创建一个公共方法
不,你可以声明:
friend class Widget;
在CompositeWidget声明中。然而...
我是在制作一个设计失礼
有一个引用派生类的父类方法可能有一点设计缺陷,但我不会说它是绝对错误的。
答案 1 :(得分:1)
使用friend
关键字。
class Widget { ... };
class CompositeWidget {
friend class Widget;
};
但是,您也可以在virtual
课程中插入AddChild
方法Widget
。
答案 2 :(得分:0)
回答您的具体问题:声明Widget
为friend
CompositeWidget
,并AddChild
成为private
成员。
或者,将子管理移至CompositeWidget
。 Design Patterns一书在Composite Pattern:
该决定涉及安全性和透明度之间的权衡:
- 在类层次结构的根目录中定义子管理界面可以提供透明度,因为您可以统一处理所有组件。然而,这会让您感到安全,因为客户可能会尝试做无意义的事情,例如在树叶中添加和删除对象。
- 在Composite类中定义子管理可以提高安全性,因为任何在叶子中添加或删除对象的尝试都将在编译时以C ++等静态类型语言捕获。但是你失去了透明度,因为树叶和复合材料有不同的界面。
我们在这种模式中强调了对安全的透明度。如果你 选择安全,然后有时您可能丢失类型信息并且有 将组件转换为组合。你怎么能没有这样做 求助于类型不安全的演员?
他们继续提供一个长代码示例,这实际上归结为CompositeWidget
包含子管理的设计:
class Widget
{
public:
//
virtual Composite* GetComposite() { return 0; }
}
class CompositeWidget: public Widget
{
public:
void AddChild(Component*);
// ...
virtual Composite* GetComposite() { return this; }
};
class LeafWidget: public Widget
{
// no child management here
};
GetComposite
可让您查询窗口小部件以查看它是否为复合窗口。您
可以安全地对它返回的复合体执行AddChild
。