一个类的某些成员是否只能通过基类访问?

时间:2014-07-03 13:34:45

标签: c++ inheritance protected composite

我有一个Widget类和一个CompositeWidget来自它。 CompositeWidget增加了儿童管理行为。 Widget构造函数将CompositeWidget*参数作为窗口小部件父级。我需要使用此父指针来访问CompositeWidget中的某些功能。例如:

Widget::Widget(CompositeWidget* parent)
{
    parent_->AddChild(*this);
}

这迫使我创建一个公共方法CompositeWidget::AddChild。可以将此接口保持为类层次结构的私有(有点像反向 - protected访问 - 仅限于基类)?在考虑这样的问题时,我是在做设计失礼吗?

编辑:我正在努力避免友谊(如果在这种情况下可行)。

3 个答案:

答案 0 :(得分:3)

  

这迫使我创建一个公共方法

不,你可以声明:

friend class Widget;

在CompositeWidget声明中。然而...

  

我是在制作一个设计失礼

有一个引用派生类的父类方法可能有一点设计缺陷,但我不会说它是绝对错误的。

答案 1 :(得分:1)

使用friend关键字。

class Widget { ... };

class CompositeWidget {
  friend class Widget;
};

但是,您也可以在virtual课程中插入AddChild方法Widget

答案 2 :(得分:0)

回答您的具体问题:声明Widgetfriend CompositeWidget,并AddChild成为private成员。

或者,将子管理移至CompositeWidgetDesign 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