By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,952 Members | 949 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,952 IT Pros & Developers. It's quick & easy.

Forward declaration doesn't seem to help to resolve the Circular dependency

P: 4
Hi guys, I'm writing a framework for an sdl gui in c++, but got stuck on the circular dependency,
I've read a lot of articles about resolving dependencies and about forward declaration but none of
them seem to work for me.
Basically I've got the Component abstract class which is the base class for all elements like
Buttons, Labels, CheckBoxes, Containers and so on. And every Component has a parent of type
Container. But here is the thing, the Container extends the Component because it should have the
same properties as Component and it also has a list of Components that belong to it.
I've tried the forward declaration but it didn't help.
Here is an example of what I mean, I can't really give you the full source code, coz it's just to big.

Expand|Select|Wrap|Line Numbers
  1. /**
  2.  * Container.h file
  3.  */
  4. #ifndef _CONTAINER_H_
  5. #define _CONTAINER_H_
  6.  
  7. #include "Component.h" // If I comment this out it gives an error about the
  8.                        // invalid use of undefined type 'struct Component'
  9.                        // see the comment below
  10.  
  11. class Component; // Forward declaration.
  12.  
  13. class Container : public Component
  14. {                      // The compiler complains here!
  15.     public:
  16.         Container();
  17.         virtual ~Container();
  18.  
  19.         Component* getChild() const;
  20.         void setChild(const Component* c);
  21.  
  22.         // Some other methods
  23.  
  24.     private:
  25.         Component* _child;
  26.  
  27.         // Some other attributes
  28. };
  29.  
  30. #endif // _CONTAINER_H_
  31.  
Expand|Select|Wrap|Line Numbers
  1. /**
  2.  * Component.h file
  3.  */
  4. #ifndef _COMPONENT_H_
  5. #define _COMPONENT_H_
  6.  
  7. #include "Container.h"
  8.  
  9. class Container; // Forward declaration.
  10.  
  11. class Component
  12. {
  13.     public:
  14.         Component();
  15.         virtual ~Component();
  16.  
  17.         Container* getParent() const;
  18.         void setParent(const Container* c);
  19.  
  20.         // Some other methods
  21.  
  22.     private:
  23.         Container* _parent;
  24.  
  25.         // Some other attributes
  26. };
  27.  
  28. #endif // _COMPONENT_H_
  29.  
Expand|Select|Wrap|Line Numbers
  1. /**
  2.  * Component.cpp file
  3.  */
  4.  
  5. #include "Container.h"
  6. #include "Component.h"
  7.  
  8. Component::Component()
  9.   : // Some initialisations
  10. {
  11. }
  12.  
  13. Component::~Component()
  14. {
  15.     // If this Component gets destroyed I've to remove it
  16.     // from the parent's list first.
  17.     if (_parent != 0)
  18.         _parent->remove(this); // This gives me an error:
  19.                                // invalid use of undefined type 'struct Container'
  20. }
  21.  
  22. // Here goes the rest of the methods
  23.  
  24.  
Some people say that the circular dependency is very bad, but this is the model
I've to implement, I mean each gui element has some common properties
that I keep in the Component class. The only thing is that each Component
must belong to some Container, which has the same properties as other Components.

Any ideas how to solve such problem?

Thanks.
Aug 13 '07 #1
Share this Question
Share on Google+
5 Replies


weaknessforcats
Expert Mod 5K+
P: 9,197
Circular references aren't bad. You just need to use them correctly. In your case I added a class forward reference to one of your header files and everything compiled without error.

Expand|Select|Wrap|Line Numbers
  1. #ifndef _CONTAINER_H_
  2. #define _CONTAINER_H_
  3.  
  4.  
  5. //#include "Component.h" // If I comment this out it gives an error about the
  6.                        // invalid use of undefined type 'struct Component'
  7.                        // see the comment below
  8.  
  9. class Component; // Forward declaration by weaknessforcats.
  10.  
  11. class Container : public Component
  12. {                      // The compiler complains here!
  13.     public:
  14.         Container();
  15.         virtual ~Container();
  16.  
  17.         Component* getChild() const;
  18.         void setChild(const Component* c);
  19.         void remove(Component* c);
  20.  
  21.         // Some other methods
  22.  
  23.     private:
  24.         Component* _child;
  25.  
  26.         // Some other attributes
  27. };
  28.  
  29. #endif // _CONTAINER_H_
  30.  
BTW I also added a Conbtainer::remove() for the compiler.
Aug 14 '07 #2

P: 4
That's strange the CodeBlocks still gives me an error at line 12 in your code. Did you compile the Component.cpp as well? Coz I also get an error when I call the remove method like this

Expand|Select|Wrap|Line Numbers
  1. _parent->remove(this);
What IDE do you use, by the way?
Aug 14 '07 #3

P: 4
Ok, it worked! Thanks a lot for your assistance weaknessforcats. I had to change it a bit to make it
work in CodeBlocks though, but it actually makes sense to me now. I suppose each compiler links those
files differently.

But here's what worked for me any way:

Expand|Select|Wrap|Line Numbers
  1. /**
  2.  * Component.h file
  3.  */
  4. #ifndef _COMPONENT_H_
  5. #define _COMPONENT_H_
  6.  
  7. class Container; // Forward declaration.
  8.  
  9. class Component
  10. {
  11.     public:
  12.         Component();
  13.         virtual ~Component();
  14.  
  15.         Container* getParent() const;
  16.         void setParent(const Container* c);
  17.  
  18.     private:
  19.         Container* _parent;
  20. };
  21. #endif // _COMPONENT_H_
  22.  
Expand|Select|Wrap|Line Numbers
  1. /**
  2.  * Container.h file
  3.  */
  4. #ifndef _CONTAINER_H_
  5. #define _CONTAINER_H_
  6.  
  7. #include "Component.h"
  8.  
  9. class Container : public Component
  10. {                // The compiler complains here!
  11.     public:
  12.         Container();
  13.         virtual ~Container();
  14.  
  15.         Component* getChild() const;
  16.         void setChild(const Component* c);
  17.         void remove(Component* c);
  18.  
  19.     private:
  20.         Component* _child;
  21. };
  22. #endif // _CONTAINER_H_
  23.  
Expand|Select|Wrap|Line Numbers
  1. /**
  2.  * Component.cpp file
  3.  */
  4. #include "Container.h"
  5. #include "Component.h"
  6.  
  7. Component::Component()
  8. {
  9. }
  10.  
  11. Component::~Component()
  12. {
  13.     // If this Component gets destroyed I've to remove it
  14.     // from the parent's list first.
  15.     if (_parent != 0)
  16.         _parent->remove(this); // This gives me an error:
  17.                                // invalid use of undefined type 'struct Container'
  18. }
  19.  
Expand|Select|Wrap|Line Numbers
  1. /**
  2.  * Container.cpp file
  3.  */
  4. #include "Container.h"
  5. #include "Component.h"
  6.  
  7. void Container::remove(Component* c)
  8. {
  9. }
  10.  
Could you please run this on your IDE and see if it works for your?
Aug 14 '07 #4

weaknessforcats
Expert Mod 5K+
P: 9,197
Yes, you are right.

What I did was paste your code into one file and compile it. In that file I had:

component.h
container.h
main()

So that is the equivalent of #include <component.h> in container.h.

I use Visual Studio.NET 2005.
Aug 14 '07 #5

P: 4
Ok, the main thing is that it makes sense to me now so I've learned something, I'd say if I come across any other circular references in the future, I'll be able to resolve it. Thanks again weaknessforcats!
Aug 14 '07 #6

Post your reply

Sign in to post your reply or Sign up for a free account.