Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Including related files

Reply
Thread Tools

Including related files

 
 
Connell Gauld
Guest
Posts: n/a
 
      06-02-2005
Hi,
I have what feels like a really stupid question and I'm sorry if it is
asked a lot.
Imagine I have two classes cShip and cPassenger. They each have a
definition in their own header cShip.h and cPassenger.h and their
implementation in cShip.cpp and cPassenger.cpp. Now here is the header
file for each:

#ifndef CSHIP_H
#define CSHIP_H

class cShip
{
...
cPassenger * owner;
...
};

#endif

------Next file

#ifndef CPASSENGER_H
#define CPASSENGER_H

class cPassenger
{
...
cShip * current_vehicle;
...
};

#endif

Now the problem I have is how to join these files together with includes
such that they compile. (The idea here is that a ship always has an
owner but that a passenger can be in a ship that they don't own).

Sorry if this is a really mundane question,
Connell
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      06-02-2005
Connell Gauld wrote:
> I have what feels like a really stupid question and I'm sorry if it is
> asked a lot.
> [...circular dependency question snipped...]


Don't be sorry, just read the FAQ before posting.
You can find it here: http://www.parashift.com/c++-faq-lite/

V
 
Reply With Quote
 
 
 
 
James Daughtry
Guest
Posts: n/a
 
      06-02-2005
An owner may not be a passenger, so it may make more sense to have a
separate cOwner and cPassenger class. But to get circular references to
compile, you can simply use a forward declaration:

#ifndef CSHIP_H
#define CSHIP_H

class cPassenger;

class cShip
{
...
cPassenger * owner;
...
};

#endif

#ifndef CPASSENGER_H
#define CPASSENGER_H

class cShip;

class cPassenger
{
...
cShip * current_vehicle;
...
};

#endif

This could cause you some problems though if any part of the class
declaration relies on deeper knowledge about the forward declared
class. A forward declaration only gives you the name of the class, not
any details about data members or member functions.

 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      06-02-2005
* Connell Gauld:
>
> I have what feels like a really stupid question and I'm sorry if it is
> asked a lot.


Not at all, it's a good question.

There are a host of very _similar_ questions that all involve
circular dependencies.

In your case the usual solution, forward declarations, is _not_
appropriate.


> Imagine I have two classes cShip and cPassenger. They each have a
> definition in their own header cShip.h and cPassenger.h and their
> implementation in cShip.cpp and cPassenger.cpp. Now here is the header
> file for each:
>
> #ifndef CSHIP_H
> #define CSHIP_H
>
> class cShip
> {
> ...
> cPassenger * owner;
> ...
> };
>
> #endif
>
> ------Next file
>
> #ifndef CPASSENGER_H
> #define CPASSENGER_H
>
> class cPassenger
> {
> ...
> cShip * current_vehicle;
> ...
> };
>
> #endif
>
> Now the problem I have is how to join these files together with includes
> such that they compile. (The idea here is that a ship always has an
> owner but that a passenger can be in a ship that they don't own).


What you have is a design problem, not (just) a technical circular
dependency problem.

Let the owner of a ship be a cPerson.

Let cPassenger be a class derived from cPerson, and voilą, problem solved;
you then have

cShip depends on CPerson
cPassenger depends on cShip and cPerson

Later on you might consider the case where the owner might be a person _or_
a corporation.

With that twist it gets more interesting...

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
Gianni Mariani
Guest
Posts: n/a
 
      06-02-2005
Connell Gauld wrote:
....
>
> Now the problem I have is how to join these files together with includes
> such that they compile. (The idea here is that a ship always has an
> owner but that a passenger can be in a ship that they don't own).


Ownership (no pun intended) is somthing you need to manage with the
code, not the declaration (if you were using smart pointers you could do
this otherwise).

As for the declaration issues - you need to forward declare the class
you're referring to - see below.

#ifndef CSHIP_H
#define CSHIP_H

class cPassenger; // declare a class cPassenger

class cShip
{
...
cPassenger * owner;
...
};

#endif

------Next file

#ifndef CPASSENGER_H
#define CPASSENGER_H

class cShip; // declare a class cShip

class cPassenger
{
...
cShip * current_vehicle;
...
};


 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      06-02-2005
Alf P. Steinbach wrote:
> * Connell Gauld:
>
>>I have what feels like a really stupid question and I'm sorry if it is
>>asked a lot.

>
>
> Not at all, it's a good question.
>
> There are a host of very _similar_ questions that all involve
> circular dependencies.
>
> In your case the usual solution, forward declarations, is _not_
> appropriate.


Huh?

> [...]

 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      06-02-2005
* Victor Bazarov:
> Alf P. Steinbach wrote:
> > * Connell Gauld:
> >
> >>I have what feels like a really stupid question and I'm sorry if it is
> >>asked a lot.

> >
> >
> > Not at all, it's a good question.
> >
> > There are a host of very _similar_ questions that all involve
> > circular dependencies.
> >
> > In your case the usual solution, forward declarations, is _not_
> > appropriate.

>
> Huh?


See the rest of that message, but, since you ask, some background:

It's generally not a good idea to solve design problems by applying
technical kludges to the _symptoms_, whether the kludges be forward
declarations, 'friend', 'void*', C-style casts, or whatever.

Such "solutions" come back to haunt you, and also they typically
yield more complex, non-maintainable code in the first place, because you
missed out on sensible abstraction opportunities (which simplify things).

Cheers,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      06-02-2005
Alf P. Steinbach wrote:
> * Victor Bazarov:
>
>>Alf P. Steinbach wrote:
>>
>>>* Connell Gauld:
>>>
>>>
>>>>I have what feels like a really stupid question and I'm sorry if it is
>>>>asked a lot.
>>>
>>>
>>>Not at all, it's a good question.
>>>
>>>There are a host of very _similar_ questions that all involve
>>>circular dependencies.
>>>
>>>In your case the usual solution, forward declarations, is _not_
>>>appropriate.

>>
>>Huh?

>
>
> See the rest of that message, but, since you ask, some background:
>
> It's generally not a good idea to solve design problems by applying
> technical kludges to the _symptoms_, whether the kludges be forward
> declarations, 'friend', 'void*', C-style casts, or whatever.


What makes you think there *is* a design problem there? The need to use
a "technical kludge" is *not* necessarily an indication of a design flaw.
Just like 'friend' and 'void*' and 'dynamic_cast', forward declarations
are there to be used to _accommodate_ certain design decisions, not to be
avoided at all costs.

> Such "solutions" come back to haunt you, and also they typically
> yield more complex, non-maintainable code in the first place, because you
> missed out on sensible abstraction opportunities (which simplify things).


No! What you did suggest was, in fact, a kludge. If two classes do
depend on each other, the model in question is _fine_, it is perfectly
OK to have a pointer to A in B and a pointer to B in A. And, yes, the
only clean way to resolve the reference "problems" is in the FAQ.

Introducing a non-existent design elements just to avoid using some
language features you might be finding "inappropriate" for whatever
reason, is definitely a mistake.

Design comes first, language-specific implementation comes second.

V
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      06-02-2005
* Victor Bazarov:
>
> Design comes first, language-specific implementation comes second.


Right.

I gather all that about likes and dislikes that I snipped abvoe, a
completely unwarranted speculation about my thinking (I don't think that
way), was really about your earlier posting, posted almost at the same time
as mine, where you failed to notice it was a design problem...

Check the design again, then tell me it's reasonable that a boat's owner
must be a passenger.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
Karl Heinz Buchegger
Guest
Posts: n/a
 
      06-02-2005
"Alf P. Steinbach" wrote:
>

[snip]
>
> Let the owner of a ship be a cPerson.


OK.
(Side note: Every cPerson owns a ship? I don't think so.
So I take it for granted that you wanted to have a cPerson class
and derive a COwner class from it)

>
> Let cPassenger be a class derived from cPerson, and voilą, problem solved;
> you then have
>
> cShip depends on CPerson
> cPassenger depends on cShip and cPerson
>
> Later on you might consider the case where the owner might be a person _or_
> a corporation.


Well. Eventually he will come to the point where his ships actually transport
cPassenger-s.

So this will end up in

cShip depends on COwner and cPassenger
cOwner depends on cShip
cPassenger depends on cShip

Same problem. The design is better, but the circular dependency stays
the same.

--
Karl Heinz Buchegger

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
including .specification files (or other "dot" files) in RakePackage on Linux/Mac OS X Nathan Beyer Ruby 0 11-15-2009 09:34 PM
How to avoid including C files in other C files in an old code base Raman C Programming 5 06-07-2008 08:43 PM
How should multiple (related) projects be arranged (structured) and configured so that they can share code, have a related package structure and enable proper unittesting, and ensuring no namespace collisions ToddLMorgan@gmail.com Python 14 04-21-2006 04:03 PM
How should threads be terminated? (related to 'Help with thread related tracebacks') Maxwell Hammer Python 7 06-18-2005 04:20 PM
Re: Protect an entire directory (including non-ASP.NET files) MS News \(MS ILM\) ASP .Net 1 08-19-2003 03:07 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57