i spin and then i lock
i spin and then i lock

Reputation: 415

C++: How to create 2 classes which use each other

This question gives answer only when the classes use each other as the member types, but not when they use the functions of each other. How to do it in the following example? Bar is a singleton container which handles the operations done on all Bars.

// Foo.h

#include "Bar.h"

class Foo {
public:
    Foo() { Bar::get_instance()->push_back(this); }

    void do_something() {}
};
// Bar.h

#include "Foo.h"
#include <vector>

class Bar {
public:
    Bar(const Bar &other) = delete;

    void operator=(const Bar &) = delete;

    static Bar *get_instance()
    {
        static Bar bar;
        return &bar;
    }

    void push_back(Foo *foo) { foos_.push_back(foo); }

    void do_something_all() { for (Foo *f : foos_) f->do_something(); }

private:
    Bar() = default;

    std::vector<Foo *> foos_;
};

Upvotes: 2

Views: 187

Answers (2)

Ted Lyngmo
Ted Lyngmo

Reputation: 117851

You split it up. Define the classes but put the implementation part after the class definition.

class Foo {
public:
    Foo(); // declare but do not implement

    // this can be implemented here since it doesn't need Bar:
    void do_something() { std::cout << "Foo::do_something()\n"; }
};

class Bar {
public:
    Bar(const Bar&) = delete;
    void operator=(const Bar&) = delete;

    static Bar& get_instance() { // return a reference instead
        static Bar bar;
        return bar;
    }

    // you can store a pointer - but require a reference:
    void push_back(Foo& foo) { foos_.push_back(&foo); }

    // or else you need to check for nullptr in here:
    void do_something_all() { for(Foo* f : foos_) f->do_something(); }

private:
    Bar() = default;

    std::vector<Foo*> foos_;
};

// Implementation part:
// Here Foo can use Bar

Foo::Foo() {
    Bar::get_instance().push_back(*this);
}

Demo

Upvotes: 3

Moia
Moia

Reputation: 2364

Forward declaration will do the trick, forward decalre in .h and include the header in cpp.

// Bar.h

//#include "Foo.h"
#include <vector>

class Foo; // <---- this one

class Bar {
public:
    Bar(const Bar &other) = delete;

    void operator=(const Bar &) = delete;

    static Bar *get_instance();

    // move definition in cpp
    void push_back(Foo *foo);

    // move definition in cpp
    void do_something_all();

private:
    Bar() = default;

    std::vector<Foo *> foos_;
};

// Bar.cpp

#include "Foo.h"

Bar* Bar::get_instance()
{
    static Bar bar;
    return &bar;
}

void Bar::push_back(Foo *foo) 
{ 
   foos_.push_back(foo); 
}
    
void Bar::do_something_all() 
{ 
   for (Foo *f : foos_) f->do_something();
}

Upvotes: 1

Related Questions