3

Just as the title state; imagine I have those two header files:

// a.h
class A {
    A();
    B operator+(A);
}

and

// b.h
class B {
    B(A);
}

Is it somehow possible to make this work using includes/forward declares?

I've of course seen many related questions but they usually either have A and B contain instance of each other (which is obviously impossible) or can be fixed with pointers or references instead of object instances. However, I still want B's constructor to actually use a A instance, is that possible?

Reizo
  • 1,374
  • 12
  • 17
  • 2
    This is called bad design and the answer is don't. You can move your operator to be a floating function though; and then you can support both `a+b` and `b+a` – UKMonkey Jan 25 '18 at 17:03
  • Possible duplicate of [Resolve build errors due to circular dependency amongst classes](https://stackoverflow.com/questions/625799/resolve-build-errors-due-to-circular-dependency-amongst-classes) –  Jan 25 '18 at 17:14
  • @UKmonkey What exact part of this is bad design? While I want to have two objects add to another, I still want to be able to create that other object using just one instance of the former. Isn't that a quite proper conception? – Reizo Jan 25 '18 at 17:38
  • @UKMonkey the argument type is same as type of `*this` so that does support arguments in both order. However, arguments aren't treated in same manner: `*this` is passed by reference, while the other argument is passed by value, so I would agree that a free function would be superior in that regard. – eerorika Jan 25 '18 at 17:41
  • @user2079303 So you mean a declaration of `B operator+(A&, A&);` outside of class `A`? I could actually see why you say this is the better solution. – Reizo Jan 25 '18 at 17:50
  • 1
    @Reizo exactly. Although, you might want to use const references. – eerorika Jan 25 '18 at 18:00

1 Answers1

3

Is it somehow possible to make this work using includes/forward declares?

It sure is.

The declaration of a function only depends on declaration of the types of its argument and the return. They don't depend on the definitions.

As such, neither class depend on the definition of the other but only on the declaration. So simply forward declare one before defining the other. B A::operator+ does depend on definition of B and B::B does depend on definition of A, so those must be defined in correct order. At least one of those has to be defined outside the definition of the class in order to satisfy the dependency requirements.

  • To define A:

    • Declare B
    • Define A
  • To define B:

    • Declare A
    • Define B
  • To define B A::operator+

    • Define A and B in any order
    • Define B A::operator+
  • To define B::B

    • Define A and B in any order
    • Define B::B

An example:

struct B;
struct A {
    B operator+(A);
};
struct B {
    B(A){}
};
B A::operator+(A) {
    return {*this};
}
int main() {
    A a;
    B b = a+a;
}
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • But the + operator returns an instance of `B`. Isn't that a dependence? I mean, the method should know the internal structure of the object it'd return, right? – Reizo Jan 25 '18 at 17:09
  • @Reizo The definition of a function does depend on the definition of the return type. Also, calling a function depends on that definition. But declaring a function does not depend on the definition of the return type but only on declaration. – eerorika Jan 25 '18 at 17:11