How can I access member function of a class via a shared ptr to a shared ptr?

Viewed 754

I have two classes, foo and bar, where bar contains a pointer to foo, as below.

#include<iostream>
#include<memory>
class foo {
private:
  int num{4};
public:
  void sum(const int& to_add) {num += to_add;}
  int access_num() {return num;}
};
class bar {
private:
  std::shared_ptr<foo> ptr;
public:
  void change_ptr(foo& f) {
    auto new_ptr = std::make_shared<foo>(f);
    ptr = std::move(new_ptr);
  }
  std::shared_ptr<foo> access_ptr() { return ptr; }
};

If I want to execute the member function sum() of foo via the pointer in bar, how do I do it? Currently, trying

  foo f;
  std::shared_ptr<bar> bar_ptr = std::make_shared<bar>();
  bar_ptr->change_ptr(f);
  // Add three to the int stored in f via the pointer
  bar_ptr->access_ptr()->sum(3);
  std::cout << f.access_num() << std::endl;

does not work, outputting 4.

1 Answers

This code

void change_ptr(foo& f) {
    auto new_ptr = std::make_shared<foo>(f); // copy constructor
    ptr = std::move(new_ptr);
}  

calls a copy constructor to create an instance of foo on the heap and manage it with std::shared_ptr. You can check it if you delete the copy constructor in foo declaration. The code won't compile. Note that you'll have to provide at least a default constructor since the rule of zero doesn't work if you have explicitly deleted copy constructor.

class foo {
private:
    int num{4};
public:
    foo() = default;
    foo(foo const &other) = delete;
    void sum(const int& to_add) {num += to_add;}
    int access_num() {return num;}
};

foo f is an automatic variable stored on the stack. There is no much use to manage it with std::shared_ptr. What you probably need is to create an instance of foo on the heap and use std::shared_ptr's to work with it:

#include<memory>

class foo {
private:
    int num{4};
public:
    void sum(const int& to_add) {num += to_add;}
    int access_num() {return num;}
};

class bar {
private:
    std::shared_ptr<foo> ptr;
public:
    void change_ptr(std::shared_ptr<foo> f) {
        ptr = std::move(f); // f is already a copy, so we can safely move it
    }
    std::shared_ptr<foo> access_ptr() { return ptr; }
};

int main() {
    auto f = std::make_shared<foo>();
    std::shared_ptr<bar> bar_ptr = std::make_shared<bar>();
    bar_ptr->change_ptr(f);
    bar_ptr->access_ptr()->sum(3);
    std::cout << f->access_num() << std::endl;
}
Related