2

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_;
};

2 Answers 2

3

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

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, upvoted as this is also the answer to my question.
1

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();
}

2 Comments

I've tried to do this, this is exactly what's suggested in the answer I was referring to. But the compiler (or at least IDE) doesn't see the Foo's do_something() function.
@kenticent move definition in .cpp. you can freely include bar.h there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.