user1899020
user1899020

Reputation: 13575

How to count an object's citation number?

Assume an object can be cited (or referenced) by other objects. Currently I use a member variable to record its citation count. The citation count is used to determine if the object can be deleted or not.

class Cited
{
public:
    int m_citationCount;
};

I make the variable public. When the object is cited, it is increased by 1. If it is uncited, it is decreased by 1. Making the variable public doesn't seem proper. If it has only one type of citer, I can make the citer type a friend. However, there may be all kinds of citers. Any better idea to do it?

More information: These objects are items or nodes in a tree structure. Some nodes may reference other nodes. For example, a node is called air which represents material air with its properties like density. A node called background may reference the air node to show the background is air. Operations on the tree are undoable. If a user deletes the background node, it is just pushed in an undo stack. It is not really deleted.

Upvotes: 0

Views: 61

Answers (2)

Mike DeSimone
Mike DeSimone

Reputation: 42825

Save yourself the grief and just use C++'s shared_ptr template.


OK, now that the question has been changed, the answer needs to as well.

Basically, you just need to employ a few strategies:

Linking using shared_ptr

Any time you need to keep track of a node, use a shared_ptr<Node> where Node is your node class. For example, if a Node needs to refer to another Node, then it has a shared_ptr<Node> to do so. For exampleworking off your example, you could have:

class Material: public Node { // Material properties here };

class Background: public Node { // Material properties here void SetMaterial(shared_ptr mat); };

void set_stage() { shared_ptr air = new Material(/constructor parameters/); shared_ptr skyBG = new Background(/constructor parameters/); skyBG->SetMaterial(air); }

Undo support

To have undo support, remember that an undo stack is generally a stack of actions, and each action contains enough information to figure out what was done (so it can be undone). If an action involves a node, then it should (like everything else) use a shared_ptr<Node> to refer to it.

Upvotes: 3

TheUndeadFish
TheUndeadFish

Reputation: 8171

You could potentially work out a scheme using a shared_ptr with a custom deleter that would do whatever you need it to when the count drops to zero.

Or you could roll something manually. At a minimum it would probably be a good idea to make the count variable private and provided public methods to do the work:

class Cited
{
public:
    void CreateCitation()
    {
        ++m_citationCount;
    }

    void RemoveCitation()
    {
        --m_citationCount;

        if(m_citationCount == 0)
        {
            // ... whatever special logic happens at zero.
        }
    }

private:
    int m_citationCount;
};

But that could be taken further by creating a Citation class to act rather like a smart pointer. Such a class would be returned by CreateCitation, would keep a pointer to the Cited object, and would call RemoveCitation in its destructor.

For example:

class Citation
{
public:
    Citation(Cited* c) : m_cited(c) {}

    ~Citation()
    {
        m_cited->RemoveCitation();
    }

    // ... whatever else to make this more usable.

    Cited* m_cited;
};

Those are just the basic ideas. There's various aspects that would need to be polished up (such as dealing with the Citation class's copy constructor and assignment operator).

Upvotes: 1

Related Questions