473,406 Members | 2,273 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

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

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
5 2938
weaknessforcats
9,208 Expert Mod 8TB
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
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
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
9,208 Expert Mod 8TB
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
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

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

Similar topics

1
by: Mohit Gupta | last post by:
Hi all, I have just started working on VC++ .Net and have problem with circular dependencies of 2 files. I created 2 forms "Form1" and "Form2", which respectively created 2 .h files, Form1.h...
6
by: Markus Dehmann | last post by:
I have a circular dependency between two classes. The FAQ hint about a forward declaration does not help in my case ( How can I create two classes that both know about each other?) Error:...
11
by: aleko | last post by:
This applies equally to function prototypes. Why do we have to tell the compiler twice? Other modern compiled languages don't have this requirement. Just curious, Aleko
2
by: verec | last post by:
Consider a first version: --- drawable.hpp --- #include "gcdata.hpp" struct drawable { ... virtual int internal_new_GC(gcdata * gcd) = 0 ; } ; --- gcdata.hpp ---
2
by: blueblueblue2005 | last post by:
Hi, there was a post several days ago about using forward class declaration to solve the circular including issue, today, one question suddenly came into mind: which class should the forward class...
3
by: François Côté | last post by:
I'm generating a TLB from one of my assemblies that contains an interface declaration. The class that implements this interface is in another assembly. I import this tlb in my C++ code to create...
2
by: Legendary Pansy | last post by:
Hello, I'm trying to accomplish the impossible by trying to do something equivalent of this example found here http://www.c-sharpcorner.com/Code/2003/Dec/DialogTutorial.as Starting with "Listing...
7
by: barias | last post by:
Although circular dependencies are something developers should normally avoid, unfortunately they are very easy to create accidentally between classes in a VS project (i.e. circular compile-time...
1
by: yancheng.cheok | last post by:
currently, i have a private function in cat named privateFun. i would like to have this function "private" to all except dog's action member function. by using the following approach, all the...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.