+ 1

Circular dependency and unresolved external symbol error at the same time C++

I will not post the code for this because it is quite long and confusing. Consider to classes A and B. What happened is that I had a problem with circular dependency (class A used B and B used A) so I moved the #include"A" from B.h to B.cpp and I declared the A class to B.h. That fixed the problem. But because class B is a template, its member functions had to be declared inside the .h file. But then I wasn't able to use the member functions of A because I only included it in the B.cpp file! I tryed also moving #include"B.h" from A.h to A.cpp and then declaring B to A.h(the opposite way), but then an object of B in the A class complained that it is from an undefined class! What should I do? Any help would be appreciated

12th Apr 2020, 7:32 PM
xaralampis_
xaralampis_ - avatar
9 Respuestas
+ 2
Circular dependency is usually a sign of bad design, you should try your best to avoid it because they are a maintenance nightmare, at the same time they can be quite tricky to solve, the way to go about it is more of a case-by-case thing. You should try and ask yourself: "Do these classes really need to know about each other? And if they do, how much do they need to know about each other?" Most of the time you'll realize that only a small portion of the class actually need to know about each other or that it makes more sense if you moved some of the functionality to a new class. Usually, if you can't solve something, the answer is: "more abstraction!". Even something that is inherently tightly coupled, like a Graph can be loosened up quite a bit. Don't forget to utilize forward declaration and pointers if need be.
12th Apr 2020, 8:46 PM
Dennis
Dennis - avatar
+ 2
Yea, 15 function pointers is not a good idea. :P I don't know what you're trying to do so it's quite hard for me to give help.
12th Apr 2020, 9:11 PM
Dennis
Dennis - avatar
+ 1
I would just make B a standalone class then, no knowledge of A whatsoever. A then instantiates a B object and then A simply uses getters/setters of B in A's functions. No need for circular dependency there. But then again, I don't know the role of B.
12th Apr 2020, 9:38 PM
Dennis
Dennis - avatar
+ 1
Yea, I don't think this is something you can solve with just 2 classes. I think you need to abstract more. Won't splitting it up into more classes work? Something like this: class Window // There is no reason for a Window to know about a Sprite or about Main { ... }; class Sprite // Why does this need to be a template? // Also Sprite doesn't need to know about Main { public: void draw( Window* window ) const { ... } ... }; class Main // Driver class, needs to know about both { public: Main() { for( const auto& sprite : sprites ) // Just an example of how to use sprite.draw( &window ); } ... private: Window window; std::vector<Sprite> sprites; }; ( Also I'm going to bed now, I'll continue tomorrow if there are any more issues )
12th Apr 2020, 10:10 PM
Dennis
Dennis - avatar
0
Dennis I total like to think that way "More abstraction!" But I think there is no other way make it even more abstract. And yes that's how I solved it using farward declaration(didn't know how it was called) and pointers but the point is that I need to access the members of the object that the pointer points to and I can't do that since I'm in the .h file and #include is in the .cpp! Finally yeah that class B does not need class A so much. The problem though is that everything that it needs is a method(15 of them) which means that the solution would be to have 15 function pointers to class B which they are all going to be initialized in constructor(that is a ctor with 15 parameters)
12th Apr 2020, 9:02 PM
xaralampis_
xaralampis_ - avatar
0
@Dennis class A is basicly the Main application, it stores a window object for now and functions that will convert some type of coordinates to others( for example screen to window coordinates ). These functions ofneed the properties of the window in order to work. I could of course make a pointer only to the window instead of the whole object. But that means that I will have to re-define these 15 methods again! I just thought though, that I can also make a new Window class which contains these methods, make an object of it in Class A and a pointer to it to class B. That would be a good solution I think :D
12th Apr 2020, 9:31 PM
xaralampis_
xaralampis_ - avatar
0
Stephan option B would be the best I think. And I just realised that I forgot to make the b object it class A a pointer... That's why it didn't work
12th Apr 2020, 9:34 PM
xaralampis_
xaralampis_ - avatar
0
B is something like sprite. It can be transformed and be rendered on the window. I like to call these Objects and the application is going to have a lot of them so A needs B a lot. That's for sure
12th Apr 2020, 9:52 PM
xaralampis_
xaralampis_ - avatar
0
@Dennis yeah sure. Thank you for all this anyway! This problem seemed impossible to solve to me before. I have a collection of solutions in my mind. I'm going to test them tomorrow. The sprite is a template for two reasons btw. The one specifies the type of vector that will help position it to the place you want on the window. The other tells basicly, whether the Object is going to be of Sprite or RectangleShape type (I'm using SFML and these 2 are the types that I use more often)
12th Apr 2020, 10:26 PM
xaralampis_
xaralampis_ - avatar