7

我经常这样做:

class Child{
  Control*parent;
public:
  Child(Control*theParent):parent(theParent){}
 };

class Control{
 Child child;
 void makeChild(){ child=Child(this); }
 //Control() : child(this) { }  //another example
 }

所以控件拥有并操作子控件,但是子控件仍然有对父控件的引用。

当我阅读有关程序设计模式等的一般主题时,似乎并不特别推荐这种组织对象的方法。我意识到存在风险,例如,您不希望您child通过让其父母做只有父母应该自己决定做的事情来滥用其父母;在这种情况下,通过确保父母的关键方法是私有的,似乎很容易防止。但是你可能有另一个控制器来管理父级,在这种情况下,一些方法应该是公共的,现在你的孩子也可以访问这些,而实际上只有其他一些控制器应该操纵这些。

所以我可以看到这有多危险。

但我的问题是,什么是常见的替代方案?您需要父母拥有孩子,但您需要孩子能够偶尔通知父母。如果不是上述情况,怎么办?

Objective-C 有 NSNotificationCenter 允许通知而不实际传递引用,但这也很容易造成组织问题(为什么我的孩子会发出这个通知,谁会收到它?)

4

4 回答 4

3

您可以通过接口将它们分开:

class IListener {
public:
    virtual void notify (int somevalue) = 0;
    ~IListener() {};
}

class Child{
private:
    IListener *listener;
public:
    Child(IListener *theListener):listener(theListener){}
};

class Control: public IListener {
private:
    Child child;
public:
    makeChild(){ child(this) };
    virtual void notify(int someValue) { doSomething(someValue);};
}

(这是观察者模式的简单版本,顺便说一句)。

于 2013-04-10T06:45:35.570 回答
2

听起来您正在寻找观察者模式。

在观察者模式中,一个对象维护一个依赖列表(也称为观察者),并根据需要通知他们更改。在您的情况下,Control类是观察者,Child类是通知者。

Boost 库有一个信号/槽机制,可用于实现这一点:http: //www.boost.org/doc/libs/1_49_0/doc/html/signals/tutorial.html#id3137144

有一个在 SO 上使用它的例子: Complete example using Boost::Signals for C++ Eventing

于 2013-04-10T06:43:19.923 回答
0

抛出另一个想法,似乎Friend 类也可以在这方面走很长的路。

孩子不应该使用的方法是制作privateprotected。这样孩子就不会造成任何你不希望它造成的伤害。

然后,如果您需要另一个类来管理您的父控制器,则您的父类将另一个类设为 a friend,以便它可以访问您对子控制器保留的所有私有方法。

于 2013-04-10T06:52:50.717 回答
0

当我阅读有关程序设计模式等的一般主题时,似乎并不特别推荐这种组织对象的方法。

这是错误的,因为控制反转。您可以将其创建为Child的成员变量。Martin Fowler 有一篇非常好的文章解释了一种控制反转(依赖注入)。

下面是一个简单解释如何实现依赖注入(通过构造函数注入依赖)的例子:

#include <iostream>

struct B
{

    virtual ~B(){}
    virtual void foo() = 0;
};
struct A1 : public B
{
    virtual ~A1(){}
    virtual void foo()
    {
        std::cout<<"hello"<<std::endl;
    }
};
struct A2 : public B
{
    virtual ~A2(){}
    virtual void foo()
    {
        std::cout<<"test"<<std::endl;
    }
};

struct C
{
    C( B &b_ ) : b(b_){}

    void bar()
    {
      b.foo();
    }

    B &b;
};

#define SAY_HI

int main()
{
#ifdef SAY_HI
    A1 a;
#else
    A2 a;
#endif
    C c(a);

    c.bar();
}

如果您考虑设计模式,您会注意到其中一些使用某种控制反转。以下是一些众所周知的(来自此链接):


顺便说一句,你所拥有的叫做责任链

于 2013-04-10T07:20:08.483 回答