2

我有 3 个不同的类(A、B、C),每个类都有一个 shared_ptr 到一个共享对象(对象 X)。我想要做的是向对象 X 提供有关谁指向它的信息。例如,如果没有指向它的 A 对象,则它不需要计算仅由 A 类在更新时使用的数据。并且对象 X 可以保留指向指向它的 C 对象的指针向量,因此当与 C 对象相关的某些数据已更新时,它可以在它们上调用函数(但 C 对象仍然指向它以从中查询其他数据)。

我正在考虑做的是为每个类上的 shared_ptr 创建一个包装器类,每当构造/分配/破坏包装器时,它将调用指向 X 上的函数的指针(所有相同的情况都会增加/减少 X 上的引用计数) . 这是代码中的想法:

class A
{
public:
    A() : m_ptr(&X::IncrementACount, &X::DecrementACount) { }

    void SetX( const std::shared_ptr<X> &ptr ) { m_ptr = ptr; }
private:
    shared_ptr_wrapper0<X> m_ptr;
};

class B
{
public:
    B() : m_ptr(&X::IncrementBCount, &X::DecrementBCount) { }

    void SetX( const std::shared_ptr<X> &ptr ) { m_ptr = ptr; }
private:
    shared_ptr_wrapper0<X> m_ptr;
};

class C
{
public:
    C() : m_ptr(this, &X::StoreCPointer, &X::RemoveCPointer) { }

    void SetX( const std::shared_ptr<X> &ptr ) { m_ptr = ptr; }
private:
    shared_ptr_wrapper1<X, const C*> m_ptr;
};

A 和 B 都有一个包装的智能指针,其中指定了不带参数的增量/减量函数。当包装的智能指针被设置/清除/等时,将在它包含的 X 对象上调用这些函数,并增加/减少 A/B 计数器。

C 有一个带有一个参数(类型为 const C* )的包装智能指针。当它被设置/清除/等时,它将使用 C 的构造函数(this 指针)存储在其上的数据调用其上的函数,并将在对象 X 上的向量中添加或删除它。

所以我的主要问题是这是个好主意吗?有没有更好的方法来实现跟踪谁在指向一个对象的想法?这种想法是否有一个具体的名称(我无法想象我是第一个尝试这样的东西的人,但我在搜索它时没有找到任何东西,所以也许我只是不知道正确的名称寻找...)

谢谢你。

4

3 回答 3

4

更简单的方法是观察者模式,也就是发布/订阅者。请参阅http://en.wikipedia.org/wiki/Observer_pattern。您的 X 对象是发布者,可以提供 3 个不同的界面供观察。您的 A、B 和 C 对象是订阅者,他们注册以收到更改通知。每个观察者负责在 X 的订阅列表中添加和删除自己。当 X 发生变化时,相应订阅列表中的每个人都会通过他们的界面收到通知。

于 2012-06-07T02:04:24.197 回答
0

您可以使用侵入式列表。制作aclass Base和 makeA并继承该类。此外,最好的技术不是区分and ,而是以相同的方式对待所有观察者(如果添加s及其特殊作用,与s 不同呢?)。这门课非常适合。BCCABDCBase

class Base
{
public:
    virtual void notifyXObjectChanged(/* data you want to pass*/) {}
    void setX(X* obj)
    {
        if(obj != object)
        {
            if(object)
                object->removeFromList(this);
            object = obj;
            if(object)
                object->addToList(this);
        }
    }

private:
    friend class X;
    X* object;
    Base* next;
    Base* previous;
};

并且,在 X 中:

class X
{
    // ...
public:
    void addToList(Base* obj)
    {
        if(first == 0 && last == 0)
        {
            // The list is empty
            first = last = obj;
            obj->previous = obj->next = 0;
        }
        else
        {
            // Add the object at the end of the list
            last->next = obj;
            obj->previous = last;
            obj->next = 0;
            last = obj;
        }
    }

    void removeFromList
    {
        // Code for removing an element in a list
    }

    void notify()
    {
        // iterate on the list
    }

private:
    Base* first;
    Base* last;
    // ...
};

优点:

  • 非常小的内存开销
  • 非常快

希望这可以帮助

于 2012-06-07T08:53:47.033 回答
0

您的问题是唯一真正指向您的 A 对象的对象是智能指针。因此,即使您可以在复制智能指针时通知您的对象(搜索侵入式指针),也无法知道在复制智能指针,这是您真正想知道的。

您需要类似 pub/sub 模型的东西。

下面是伪代码,给出的想法是,我们要跟踪两种不同类型的订阅者。

class A
{
private:
    std::vector<B&> subscriberB;
    std::vector<C&> subscriberC;

public:
    void Subscribe(const B& subscriber) { subscriberB.push_back(subscriber); }
    void Subscribe(const C& subscriber) { subscriberC.push_back(subscriber); }

    // An example of a function where the subscribing objects are notified.
    void SomeFunction()
    {
        // for each subscriber in subscriberB
        subscriber.SomeFunction();

        // for each subscriber in subscriberC
        subscriber.SomeOtherFunction();
    }

};

上面存储引用,假设订阅者比他们订阅的对象寿命长。如果没有,您应该将智能指针放在向量中。此外,您可能希望防止同一个对象订阅两次,或者提供一种取消订阅的方法。

如果您想“强制”类型 B 或 C 的对象与 A 关联,您可以使它们的构造函数类似于:

// B ctor
B::B(shared_ptr<A> aPtr)
{
    myPointerToA = aPtr;
    myPointerToA ->subscribe(*this);
}

更好的是使用创建 B 的工厂方法,然后将其连接到 A:这避免this了构造函数中的取消引用,这有点臭。

一种更典型的方法是拥有单一类型的订阅者“InterfaceSubscribeToA”,任何想要订阅 A 的类都将实现该订阅者。这完全取决于您要实现的目标,我只是提一下,以防您碰巧使您的特定问题过于复杂!

于 2012-06-07T05:13:56.743 回答