C++ – How to deal with pointers from child to parent

cc++11class-design

I have a class that represents a file in specific binary format on disk (the parent in the title) and another class that represents an object inside that file (child). When the object changes, it sometimes needs to relocate to a new position in the file and the file class has to be notified about this new position.

To do this, I have added a weak_ptr field to object, which points to the file. Except that means there has to be a shared_ptr for file, so I'm using a static factory method instead of public constructor for it. And object now can't be initialized in the constructor, so I'm using unique_ptr for it.

In code, it looks something like this:

class File;

class Object
{
private:
    std::weak_ptr<File> file;

public:
    Object(std::weak_ptr<File> file)
        : file(file)
    {}

    void modify();
};

class File
{
private:
    std::unique_ptr<Object> object;
    std::shared_ptr<File> self;

    File()
    {}

public:
    void setObjectPosition(std::uint64_t newPosition);

    static std::shared_ptr<File> create();
};

void Object::modify()
{
    std::uint64_t newPosition = …;

    file.lock()->setObjectPosition(newPosition);
}

void File::setObjectPosition(std::uint64_t objectPosition)
{
    // store objectPosition
}

std::shared_ptr<File> File::create()
{
    auto file = std::shared_ptr<File>(new File());

    file->self = file;
    file->object = std::unique_ptr<Object>(new Object(file));

    return file;
}

Is this this the right approach to do this? Or is there a better/more idiomatic solution? I feel like I'm using *_ptr too much, but I can't think of anything better.

Best Answer

If all you need is a non-owning pointer to an object, just use a raw pointer. Here's a smaller example:

template <typename T> struct binary_tree_node
{
    std::unique_ptr<binary_tree_node> left_child_;
    std::unique_ptr<binary_tree_node> right_child_;
    binary_tree_node* parent_ = nullptr;
    T data_; 
};

shared_ptr and unique_ptr imply some kind of ownership, which child->parent does not have, since the parent owns the child. Therefore a raw pointer is totally okay in this situation(just don't delete it!)

Related Topic