0
votes

I have two classes, for instance, A and B. I would like to pass A as reference to B.

class I
{
public:
    virtual void callback() = 0;
};

class B
{
public:
    B(I* callback) : _callback(callback) {}
private:
    I* _callback;
};

class A : public I
{
public:
    A() : _b(new B(this)) {}
private:
    B* _b;
};

And I would like to:

  1. get rid of naked pointers (for instance, with a help of std::shared_ptr and std::weak_ptr).
  2. avoid cyclic referencing.

But there are some problems:

  1. How do I create a weak pointer INSIDE a class A? First, I should be sure that an instance of A is managed by some shared_ptr. Even if I'm really sure, how can I find this shared_ptr instance?
  2. Generally, how can I ensure that I'm using instances of some class ONLY via shared pointers? I can try to create factory method and make constructor private, but it leads to error: make_shared demands a public contstructor.

Thanks in advance!

EDIT:

More detail explanation of problem: I have a class A. This class wants to pass some part of work to a class B. So I have a shared pointer to B inside A. And I would like B to do this asynchronously, and B should call A's callback when there is some progress or when the work is done. So B should have a reference to A.

class I
{
public:
    virtual void isDone() = 0;
};

class B
{
public:
    B(I* callback) : _callback(callback) //how do I take and store callback inside B???
    {
        //async invocation of run()
    }
private:
    weak_ptr<I> _callback;

    void run()
    {
        if(_callback.get())
        {
            _callback->isDone();
        }
    }
};

class A : public I
{
public:
    A() : _b(new B(this)) {} //how do I pass this to B???
private:
    shared_ptr<B> _b;

    virtual void isDone()
    {
        cout << "job is complete" << '\n';
    }
};

So the question is: how do I pass A to B? I can try to do it via naked pointer or reference, but it's safety because B has no guarantees that this referenced object is still alive (common problem of all naked pointers). So I would like to pass a weak pointer, and my question was all about it.

1
Don't see any std::weak_ptr in your sample?? - πάντα ῥεῖ
@πάνταῥεῖ this example is an origin of problem. To use a weak pointer properly is an essence of the question :). - slashdot
Usually it helps for SO questions, to show what you have tried, and why it didn't work. - πάντα ῥεῖ
I'd use a full shared pointer in this case, not a weak pointer. Use a weak_ptr if you want to allow the object to go out of scope and then handle that situation, but in this case you don't want the object to go out of scope. Since you are already using the shared pointer, it doesn't add any overhead to use more instances of the shared pointer. - IdeaHat
@MadScienceDreams but what about cyclic referencing? If A have a shared pointer to B and B have shared pointer to A? - slashdot

1 Answers

2
votes

The first problem can be solved with std::enable_shared_from_this, which allows you to safely create a shared pointer instance from within class A.

The second problem may be solved by using a static factory method belonging to class A and not using std::make_shared like this:

static std::shared_ptr<A> create() {
    return std::shared_ptr<A>(new A());
}

Then, you can make A's constructor private.