c++pointersobjectinstances

How to share an object between two classes


I have two classes, Foo and Bar. They both contain a pointer to a Baz object. I want the Baz pointers in both an instance of Foo and an Instance of Bar to point to the same Baz object.

A Baz object has a member called name with getter and setter functions.

A Foo object contains a Bar object.

A Bar object has a method to print the name of the Baz object.

The Baz objects name must be set in the scope of Foo.

This is what I have tried:

In the constructor of Foo, it sets the name of this bazA, and sets the bazB belonging to bar to be equal to the bazA belonging to Foo.

//Foo.h
class Foo {
public:
    explicit Foo();
    Baz* bazA;
    Bar bar;
}

//Foo.cpp
Foo::Foo()
{
     this->bazA->setName("hello");
     this->bar.bazB = bazA;
}

//Bar.h
class Bar{
public:
    Baz* bazB;
    void printName ();
}

//Bar.cpp
void Bar::printName ()
{
     std::cout << "name: " << bazB->getName();
    //Should print out "name: hello"
}

When I do this:

//Main.cpp
Foo foo;
foo.bar.printName();

The program crashes because the name member has not been initialised in the Baz object that belongs to the Bar object.

But the Baz object belonging to Bar should be the same Baz object that belongs to Foo, which has had its name set, so it should work.

Why am I getting this error?

How can I correctly share a Baz object between the Foo and Bar classes?


Solution

  • The code you have to share the objects is correct: Foo creates the Baz, then passes it to the Bar. The issue is you are not constructing the Baz properly:

    Foo::Foo()
    {
         this->bazA->setName("hello"); // crash because bazA hasn't had memory allocated
         this->bar.bazB = bazA; // setting bazB to invalid memory
    }
    

    Instead, you should just have an object of Baz in Foo, and share it with Bar:

    class Foo {
    public:
        Foo();
        Baz bazA;
        Bar bar;
    }
    
    Foo::Foo()
    {
         bazA.setName("hello");
         bar.bazB = &bazA;
    }
    

    Even better, Bar's constructor should take a Baz reference instead:

    class Bar
    {
    public:
        Bar(Baz& b) : bazB(b){}
    private:
         Baz& bazB;
    };
    
    Foo::Foo()
        : bazA(), bar(bazA)
    {
        bazA.setName("hello");
    }
    

    Here I assumed that Class and Public were typos and corrected them.