-3

I working on a project and I have a lot of classes that have instances of other classes as fields. The problem is that I must declare the classes in a specific order in order for the code to compile. Example below:

class A{
  public:
    B* b; //unknown type name B
    A(){
      b = new B();
    }
};

class B{
  public:
    B(){
    }

};

The code above does not work, because it says that B is unknown. But, if I declare class B before A it's working fine.

class B{
  public:
    B(){
    }

};

class A{
  public:
    B* b; //Works perfectly
    A(){
      b = new B();
    }
};

In my project, there's no way to re-arrange the classes in order for the error to go away. Is there a way to bypass this error?

Alex Matt
  • 209
  • 1
  • 4
  • 6
    Possible duplicate of [What are forward declarations in C++?](https://stackoverflow.com/questions/4757565/what-are-forward-declarations-in-c) – Yksisarvinen Feb 28 '19 at 12:49
  • Possible duplicate of [Mutually recursive classes](https://stackoverflow.com/questions/3410637/mutually-recursive-classes) – Botje Feb 28 '19 at 12:49
  • 1
    Classes should almost always be kept in seperate files. This allows you to #include them as headers to avoid such problems – Tom Feb 28 '19 at 12:49
  • 2
    Please fix your example. In your example there is no reason why `B` cannot go before `A`, so the problem seems to be something you are not telling us – 463035818_is_not_an_ai Feb 28 '19 at 12:50
  • @user463035818 That's not the problem. The question is, can I make it work by arranging the classes any way I want? Ergo, can I make it work with B below A? – Alex Matt Feb 28 '19 at 12:53
  • unless you tell us why the obvious solution does not work for you it is difficult, if not impossible, to answer that (and tbh rather pointless imho) – 463035818_is_not_an_ai Feb 28 '19 at 12:55
  • i mean you can use a forward declaration, but given that your example here differs from your real problem, who knows if that can work for you... – 463035818_is_not_an_ai Feb 28 '19 at 12:56
  • 1
    @AlexMatt as mentioned by Tom, the canonical way to implement classes is with division to header and source file. If you did that, you wouldn't encounter this problem. The other solution is to just reorder them, since `B` does not depend on `A`. Third solution is in duplicate I provided, which is forward declaring class `B` before declaring class `A`. – Yksisarvinen Feb 28 '19 at 12:57

1 Answers1

1

In my project, there's no way to re-arrange the classes in order for the error to go away. Is there a way to bypass this error?

You are describing a circular dependency. X depends on Y and Y depends on X. Such dependency is unsolvable. If you can remove a dependency on one class from another class, then it may be possible to re-order the definitions so that all dependencies are satisfied. Sometimes dependency can be removed by introducing indirection.

Note that just because one class definition (A) depends on declaration of another class (B), that doesn't necessarily mean that it depends on the definition of that class. You can have one class depend on the definition of another class, while still having the dependee class depend on the declaration of the depender.

Furthermore, just because definition of a member function (A::A) depends on definition of another class (B), that doesn't necessarily mean that the class (A) has that same dependency. This is because it is not necessary to define member functions within the class definition.

For example, your example class A does not depend on the definition of B. As such, A can be defined before B:

// declaration of B
// not a definition
class B;

// definition of A
class A{
  public:
    B* b;   // depends on declaration of B
            // does not depend on the definition
    A();
};

// definition of B
class B{
  public:
    B(){
    }
};

// definition of A::A
// does depend on definition of B
A::A() {
    b = new B();
}
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • @Yksisarvinen I did not (nor did OP) say that there is a circular dependncy between `A` and `B`. OP said that they have a cirular dependency in their project. Their example with `A` and `B` does not demonstrate a circular dependency. It simply demonstrates a dependency and how it imposes a restriction on order of definitions. My example shows how the dependency in the example does not restrict the order of definition of the classes, because the class definition of `A` only depends on the declaration of `B`. The restriction still applies to the definition of `A::A`. – eerorika Feb 28 '19 at 13:55
  • @Yksisarvinen I'll keep mine, since others may have the same question, and I don't want to bloat the answer further. (Extra note: Whether OP is correct in their description of their project is not something we can determine). – eerorika Feb 28 '19 at 14:05