0

Hypothetical situation that I'm struggling to get my head past.

HoldsFooBar.h:
#include "foo.h"
#include "bar.h"
class HoldsFooBar{
    foo F;
    bar B;
};


foo.h:
//includes?
class foo{
    HoldsFooBar *H;
    void Baz();
};


bar.h:
//includes?
class bar{
    HoldsFooBar *H;
    void Qux();
};

I'm trying to get F to get a hold of B. In all other languages I've worked with, I would be able to H->B.Qux();, but I'm totally lost in C++. At the includes lines in foo.h and bar.h, it seems like my options are to forward-declare class HoldsFooBar; but then I can only access H, and F and B cannot see each other. Likewise, I can #include "HoldsFooBar.h" but because of my include guards, something ends up not getting linked properly, so the program doesn't run.

Is what I'm trying to do even possible? Thank you very much! Any help would be appreciated!

ʇolɐǝz ǝɥʇ qoq
  • 717
  • 1
  • 15
  • 30
  • For one, you're not going anywhere without using `->` rather than `.` for member access of `H`. And you can forward-decl `HoldsFooBar` in both foo.h and bar.h as you described and use in a .cpp file where you also include `HoldsFooBar.h`. – WhozCraig Jun 03 '14 at 02:55
  • It's pseudocode. Ignore tiny irrelevant mistakes like -> vs . – Greg Kritzman Jun 03 '14 at 02:56
  • possible duplicate of [C++ - How to call creator class/object](http://stackoverflow.com/questions/3422854/c-how-to-call-creator-class-object) – Nav Jun 03 '14 at 02:58
  • Also, say I forward declared HoldsFooBar in foo. I could then have access to H, but it wont let me access H->B. – Greg Kritzman Jun 03 '14 at 02:58
  • "Ignore tiny irrelevant mistakes like -> vs ." - does that include a lack of access specifiers? Given your description of your C++ familiarity, I can't tell whether you'd know about them. Anyway, you need `public:` before `class` members that you want generally available to other code (and - when applicable - `protected:` for members that should only be accessible to derived classes). – Tony Delroy Jun 03 '14 at 04:01
  • Yes, I know about those, and in real code, am sure to implement them. If you feel like you're not answering the main question, it's probably safe to consider it irrelevant in this context. – Greg Kritzman Jun 04 '14 at 17:35

3 Answers3

2

Possible with -> as noted by WhozCraig, but strongly discouraged. This is an instance of a god object, an OOP anti-pattern.

Patrick Collins
  • 10,306
  • 5
  • 30
  • 69
  • Why is having a god object discouraged? I've used them in the past, and it's really convenient. Sometimes I want to reference several odd pieces of architecture from another odd one, and it's nice to only have to have one pointer (to the god object) as opposed to a wide array of them. – Greg Kritzman Jun 03 '14 at 03:06
  • There's a great SO post here: http://programmers.stackexchange.com/questions/178317/how-do-i-prove-or-disprove-god-objects-are-wrong – Patrick Collins Jun 03 '14 at 03:08
  • 1
    Well shoot. I guess it's time to rethink my architecture and try to figure a proper way to do all of this. Thanks for advising me. – Greg Kritzman Jun 03 '14 at 03:20
1

If you really need to access both foo from bar.Qux and bar from foo.Baz, just pass them as arguments to the relevant functions:

foo.h:
//includes?
class foo{
    void Baz(bar &barInstance);
};


bar.h:
//includes?
class bar{
    void Qux(foo &fooInstance);
};

Or, if you're gonna need a "pair" of foo and bar, that will be dependant, maybe the way here is actually combining the objects into one? If that doesn't suit you, maybe try passing them inside the constructor?

class foo{
   bar &myBarFriend;
   foo(bar& b):myBarFriend(b){};
};

Note that you'll still need to use forward-declarations here.

Paweł Stawarz
  • 3,952
  • 2
  • 17
  • 26
0

Although I would discourage the practice, for a circular reference, you need a forward declaration. Have a look at these answers: C++ - How to call creator class/object

Community
  • 1
  • 1
Nav
  • 19,885
  • 27
  • 92
  • 135