c++ - Resolve build errors due to circular dependency amongst classes -


i find myself in situation facing multiple compilation/linker errors in c++ project due bad design decisions (made else :) ) lead circular dependencies between c++ classes in different header files (can happen in same file). fortunately(?) doesn't happen enough me remember solution problem next time happens again.

so purposes of easy recall in future going post representative problem , solution along it. better solutions of-course welcome.


  • a.h

    class b; class {     int _val;     b *_b; public:      a(int val)         :_val(val)     {     }      void setb(b *b)     {         _b = b;         _b->print(); // compiler error: c2027: use of undefined type 'b'     }      void print()     {         cout<<"type:a val="<<_val<<endl;     } }; 

  • b.h

    #include "a.h" class b {     double _val;     a* _a; public:      b(double val)         :_val(val)     {     }      void seta(a *a)     {         _a = a;         _a->print();     }      void print()     {         cout<<"type:b val="<<_val<<endl;     } }; 

  • main.cpp

    #include "b.h" #include <iostream>  int main(int argc, char* argv[]) {     a(10);     b b(3.14);     a.print();     a.setb(&b);     b.print();     b.seta(&a);     return 0; } 

the way think "think compiler".

imagine writing compiler. , see code this.

// file: a.h class {   b _b; };  // file: b.h class b {   _a; };  // file main.cc #include "a.h" #include "b.h" int main(...) {   a; } 

when compiling .cc file (remember .cc , not .h unit of compilation), need allocate space object a. so, well, how space then? enough store b! what's size of b then? enough store a! oops.

clearly circular reference must break.

you can break allowing compiler instead reserve space knows upfront - pointers , references, example, 32 or 64 bits (depending on architecture) , if replaced (either one) pointer or reference, things great. let's replace in a:

// file: a.h class {   // both these fine, various const versions of same.   b& _b_ref;   b* _b_ptr; }; 

now things better. somewhat. main() still says:

// file: main.cc #include "a.h"  // <-- houston, have problem 

#include, extents , purposes (if take preprocessor out) copies file .cc. really, .cc looks like:

// file: partially_pre_processed_main.cc class {   b& _b_ref;   b* _b_ptr; }; #include "b.h" int main (...) {   a; } 

you can see why compiler can't deal - has no idea b - has never seen symbol before.

so let's tell compiler b. known forward declaration, , discussed further in this answer.

// main.cc class b; #include "a.h" #include "b.h" int main (...) {   a; } 

this works. not great. @ point should have understanding of circular reference problem , did "fix" it, albeit fix bad.

the reason fix bad because next person #include "a.h" have declare b before can use , terrible #include error. let's move declaration a.h itself.

// file: a.h class b; class {   b* _b; // or of other variants. }; 

and in b.h, @ point, can #include "a.h" directly.

// file: b.h #include "a.h" class b {   // note cool because compiler knows time   // how space need.   _a;  } 

hth.


Comments

Popular posts from this blog

unity3d - Rotate an object to face an opposite direction -

angular - Is it possible to get native element for formControl? -

javascript - Why jQuery Select box change event is now working? -