473,508 Members | 2,281 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Cyclic Dependency Problem

147 New Member
Hi, got a possibly stupid question. I have 2 header files each containing class definitions along the lines of:
Expand|Select|Wrap|Line Numbers
  1. // Header1.h
  2. #pragma once
  3. #include "Header2.h" // for Class2
  4.  
  5. class ClassA
  6. {
  7.   Class2 m_class1;
  8. };
  9.  
  10. class ClassB
  11. {
  12.   int whatever;
  13. };
Expand|Select|Wrap|Line Numbers
  1. // Header2.h
  2. #pragma once
  3. #include "Header1.h"  // for ClassB
  4.  
  5. class Class1
  6. {
  7.   ClassB m_classB;
  8. }
  9.  
  10. class Class2
  11. {
  12.   int someThing;
  13. };
Merging the files together isn't possible. Changing the class definitions isn't possible (I am using them but did not write them).
How can I get this to compile?
Sep 22 '08 #1
6 2708
boxfish
469 Recognized Expert Contributor
Two words: Forward Declaration.
You can let the compiler know about ClassB and Class2 before it sees them. Just use the statements
class ClassB;
and
class Class2;
Then you can use the names ClassB and Class2 before they are defined.

So:

Expand|Select|Wrap|Line Numbers
  1. // Header1.h
  2. #pragma once
  3. #include "Header2.h" // for Class2
  4.  
  5. class Class2;
  6.  
  7. class ClassA
  8. {
  9. Class2 m_class1;
  10. };
  11.  
  12. class ClassB
  13. {
  14. int whatever;
  15. };
  16.  
And:

Expand|Select|Wrap|Line Numbers
  1. // Header2.h
  2. #pragma once
  3. #include "Header1.h" // for ClassB
  4.  
  5. class ClassB;
  6.  
  7. class Class1
  8. {
  9. ClassB m_classB;
  10. }
  11.  
  12. class Class2
  13. {
  14. int someThing;
  15. };
  16.  
Hope this helps.
Sep 22 '08 #2
scruggsy
147 New Member
Two words: Forward Declaration.
I appreciate that, but it doesn't help in this instance because each class contains an object of a class defined in the other file rather than just a pointer to such an object, so the compiler needs to know what the contained object looks like in order to construct the containing class.

I managed to work around it in this case using a forward declaration due to the way one of the classes is laid out (class1 actually looks more like this):
Expand|Select|Wrap|Line Numbers
  1.  class Class1
  2.  {
  3. struct Data {
  4.  ClassB m_classB;
  5.   int someMoreData;
  6. };
  7.  
  8. Data * data;
  9.  };
I can redefine data as a pointer to a ClassB object and do some ugly pointer arithmetic to get at the someMoreData member of the struct, which works mainly because I don't need to create objects of Class1, just interface with them.
But I expect this kind of issue comes up occassionally and I am curious how people solve it.
Sep 22 '08 #3
Banfa
9,065 Recognized Expert Moderator Expert
But I expect this kind of issue comes up occassionally and I am curious how people solve it.
That is very poor class design and/or file design (the problem wouldn't occur if you stuck to the simple rule 1 class per file pair (*.h, *.cpp).

There is no way round it without either altering one of the classes to make forward declaration possible or re-organising the filesso there are more containing less classes.
Sep 22 '08 #4
weaknessforcats
9,208 Recognized Expert Moderator Expert
The only way a forward declaration works is if the class has a pointer to the other class.

If the class contains an object of another class, the forward declaration doesn't work becuse the compiler needs to see of there is a default constructor or not.
Sep 22 '08 #5
donbock
2,426 Recognized Expert Top Contributor
Define a third header file that contains all of the intertwined declarations from the original headers. Then modify the original header files to include that new file.

The header contents you supplied suggest that there is a single logical entity that encompasses some of the features in each of the original files. This new third header file I'm suggesting is for that logical entity.

Intertwined headers like this suggest a problem in the design that led to this file partitioning. You might want to look up the terms "coupling" and "cohesion" as used to describe properties of a software design.

By the way, don't forget to make your header files idempotent. That is, no errors should be provoked by including them more than once.

Cheers,
donbock
Sep 22 '08 #6
scruggsy
147 New Member
Define a third header file that contains all of the intertwined declarations from the original headers. Then modify the original header files to include that new file.

The header contents you supplied suggest that there is a single logical entity that encompasses some of the features in each of the original files. This new third header file I'm suggesting is for that logical entity.

Intertwined headers like this suggest a problem in the design that led to this file partitioning. You might want to look up the terms "coupling" and "cohesion" as used to describe properties of a software design.

By the way, don't forget to make your header files idempotent. That is, no errors should be provoked by including them more than once.

Cheers,
donbock
Thanks, I think that should be doable although it's a bit of a change from how we have been organizing the class definitions. I suppose this issue would be less likely to come up if we were designing from scratch rather than documenting someone else's classes.
Sep 22 '08 #7

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

Similar topics

7
2732
by: Brian Sabolik | last post by:
I'm not sure if I've broken any Object Oriented rules or not, but ... I have projects in 2 different solutions that need to use each other's methods. Therefore I may have an "update" method in...
3
2221
by: Dennis Lerche | last post by:
Hi I have a problem regarding cyclic dependency, yeahh I know bad design. But right at this moment I can't see how it should be redesigned to avoid this. The problem is that I just can't get it...
0
1418
by: Scott Ribe | last post by:
I've got a problem which I think may be a bug in Postgres, but I wonder if I'm missing something. Two tables, A & B have foreign key relations to each other. A 3rd table C, inherits from A. A...
4
4535
by: Alex Sedow | last post by:
For example, System.dll contains assembly reference to System.XML.dll, System.XML.dll refers to System.dll. Some another open projects contain cyclic assembly dependencies too. How C# compiler...
3
2104
by: Pohihihi | last post by:
This is a report from VSS newsgroup in hope of getting some more suggestions. Thanks, Po ------------------------------------------- I guess I am not getting the whole picture here. How does...
3
2725
by: fc2004 | last post by:
Hi, Is there any tools that could report where cyclic header dependency happens? this would be useful when working with a large project where tens or hundreds of headers files may form complex...
4
1714
by: sakis.panou | last post by:
Hi all, Can anyone explain to me why the copy constructor of the COuterClass is getting called for this one? Let me start by saying I reckon this is seriously bad way of implementing anything of...
1
677
by: pallav | last post by:
I have to header files, circuit.h and latch.h that reference each other and are causing a cyclic dependency. latch.h file #include "circuit.h" typedef boost::shared_ptr<struct LatchLatchPtr;...
3
1742
by: soup007 | last post by:
Hi, I am having some difficulties with cyclic dependency between two classes. Situation is something like following - ///A.h #include "B.h" class A { { int X; public:
11
3185
by: sgurukrupagmailcom | last post by:
Hi, When searching for a solution to my problem I stumbled upon 'Curiously Recurring Template Pattern' see link. This is how the pattern looks: template < typename T > struct y { } ;
0
7123
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
7324
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
7495
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
5627
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,...
1
5052
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4707
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3193
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
1556
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
766
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.