Cross-referencing classes 
Author Message
 Cross-referencing classes

I run into this problem a lot. I create two classes, and each must call a
method in the other. So, which ever one comes first when the application is
compiled complains it doesn't know about the other's METHOD yet.

The only work around I've found is to separate the code (.cpp) and the
declarations for the class(.h). But, this is not my style. It also
eliminates the use of 'inline' if I like to keep all my class code in one
place. It also means the other class can never call an inline method of a
cross-referencing class.

I like to keep all of my class declarations and code in one file, a header
(.h). But I really can't. I know why this is true, it's because VC is a
single pass compiler. Any chance there might be, or ever will be, an option
to let it be a double pass compiler which takes care of cross-referencing?
This would also allow, amongst other things,  placing the inline methods of
a class outside the header and in a separate code (.cpp) file.

 My two cents... :)

 /== Peteroid ==\



Fri, 25 Feb 2005 03:15:34 GMT  
 Cross-referencing classes

Quote:
> I run into this problem a lot. I create two classes, and each must call a
> method in the other. So, which ever one comes first when the application
is
> compiled complains it doesn't know about the other's METHOD yet.

Perhaps you're looking for forward declarations..

struct X;

struct Y
{
  void f(X& x);

 void h()
 {
 }

Quote:
};

struct X
{
  void g(Y& y)
  {
    y.h();
  }

Quote:
};

inline void Y::f(X& x)
{
  x.g(*this);

Quote:
}

HTH
-cd


Fri, 25 Feb 2005 04:35:13 GMT  
 Cross-referencing classes
Hi Carl,

Your example doesn't illustrate what I'm talking about, since it requires
cross-referenced class METHODS. Change X and Y to classes (can structures
have methods?) , and add a method to class X (let's call it j( )) and then
the question becomes how to use this function in class Y (which is defined
before it)?

The problem is class X can use any method of class Y since all of class Y's
methods are declared before class X's definition, but class Y can't access
any method of class X since the methods of class X are declared later (in
our case, X::j( ) can't be used in class Y). Reversing the order of defining
classes X and Y would cause an error when class X tries to use Y::h( )
(since now it won't be declared until after class X must be entirely
defined).

This never use to happen with two-pass compilers since it first makes a
symbol table (during first pass),  and then knows about both class X and Y
during the second pass where it actually generates code. In my case, I'm
taking a lot more time trying to figure out how to make things work for a
single-pass compiler than the added compile time a two-pass compiler would
cost me... :)

  /== Peteroid ==\


Quote:


> > I run into this problem a lot. I create two classes, and each must call
a
> > method in the other. So, which ever one comes first when the application
> is
> > compiled complains it doesn't know about the other's METHOD yet.

> Perhaps you're looking for forward declarations..

> struct X;

> struct Y
> {
>   void f(X& x);

>  void h()
>  {
>  }
> };

> struct X
> {
>   void g(Y& y)
>   {
>     y.h();
>   }
> };

> inline void Y::f(X& x)
> {
>   x.g(*this);
> }

> HTH
> -cd



Fri, 25 Feb 2005 05:25:19 GMT  
 Cross-referencing classes
Should be possible by breaking the code up into three place, for each co-dependent class:

a header file purely of prototypes/class definitions
an inline file of the actual inline code.
and .cpp source files files of normal (non-inlined) code

    Then its simply a matter of including all the headers followed by all the inline files.  Forward declarations can
also usually handle most cases, as any function prototypes just passing a pointer or reference of a struct or class can
be forward declared without needing any knowledge of the other class's internals.

    You should generally only inline what you have to (though in the case in math libraries that is typically
everything) or you will find yourself recompiling constantly making changes to code.  A way to avoid this problem is to
include the inline file in .cpp file and compile as not-inline for debug, and as inline in release only, which also
requires some #define trickery to decorate the functions as inline or not, conditionally.  Aggressive forward
declarations in headers with as few #includes inside headers as possible to other headers is a good way to decrease
build times (and including the headers you actually really use inside .cpp files) esp when changing class interfaces, as
only code actually using the class will be rebuilt instead of everything that pulled its interface in through
unnecessary #includes via headers.

    And to the first question, structs can have methods (as well as constructors/destructors and virtual functions).  In
C++ they are just class's that are automatically all public.  Most people follow the convention that structs are safe to
be malloc'd calloc'd realloc'd and memset, so they usually only end up with non-virtual methods and no constructor or
destructor.

Quote:

> Hi Carl,

> Your example doesn't illustrate what I'm talking about, since it requires
> cross-referenced class METHODS. Change X and Y to classes (can structures
> have methods?) , and add a method to class X (let's call it j( )) and then
> the question becomes how to use this function in class Y (which is defined
> before it)?

> The problem is class X can use any method of class Y since all of class Y's
> methods are declared before class X's definition, but class Y can't access
> any method of class X since the methods of class X are declared later (in
> our case, X::j( ) can't be used in class Y). Reversing the order of defining
> classes X and Y would cause an error when class X tries to use Y::h( )
> (since now it won't be declared until after class X must be entirely
> defined).

> This never use to happen with two-pass compilers since it first makes a
> symbol table (during first pass),  and then knows about both class X and Y
> during the second pass where it actually generates code. In my case, I'm
> taking a lot more time trying to figure out how to make things work for a
> single-pass compiler than the added compile time a two-pass compiler would
> cost me... :)

>   /== Peteroid ==\



Fri, 25 Feb 2005 06:48:04 GMT  
 Cross-referencing classes

Quote:
> Hi Carl,

> Your example doesn't illustrate what I'm talking about, since it requires
> cross-referenced class METHODS. Change X and Y to classes (can structures
> have methods?) ,

struct - class: makes no difference.

Quote:
> and add a method to class X (let's call it j( )) and then
> the question becomes how to use this function in class Y (which is defined
> before it)?

That's precisely what Y::f() does - read again.

-cd



Fri, 25 Feb 2005 06:49:24 GMT  
 Cross-referencing classes
I think in this case of cross referencing it's best to use seperate header
files with declarations only. If you want to inline while keeping all the
implementation code in the cpp file you should look at the Whole Programl
Optimization option of vc7. I hope I don't say something wrong here but with
this option turned on it's possible to inline functions across obj files. If
I remember correctly Matt Pietrek wrote about it in MSDN Magazine.


Quote:
> Hi Carl,

> Your example doesn't illustrate what I'm talking about, since it requires
> cross-referenced class METHODS. Change X and Y to classes (can structures
> have methods?) , and add a method to class X (let's call it j( )) and then
> the question becomes how to use this function in class Y (which is defined
> before it)?

> The problem is class X can use any method of class Y since all of class
Y's
> methods are declared before class X's definition, but class Y can't access
> any method of class X since the methods of class X are declared later (in
> our case, X::j( ) can't be used in class Y). Reversing the order of
defining
> classes X and Y would cause an error when class X tries to use Y::h( )
> (since now it won't be declared until after class X must be entirely
> defined).

> This never use to happen with two-pass compilers since it first makes a
> symbol table (during first pass),  and then knows about both class X and Y
> during the second pass where it actually generates code. In my case, I'm
> taking a lot more time trying to figure out how to make things work for a
> single-pass compiler than the added compile time a two-pass compiler would
> cost me... :)

>   /== Peteroid ==\





> > > I run into this problem a lot. I create two classes, and each must
call
> a
> > > method in the other. So, which ever one comes first when the
application
> > is
> > > compiled complains it doesn't know about the other's METHOD yet.

> > Perhaps you're looking for forward declarations..

> > struct X;

> > struct Y
> > {
> >   void f(X& x);

> >  void h()
> >  {
> >  }
> > };

> > struct X
> > {
> >   void g(Y& y)
> >   {
> >     y.h();
> >   }
> > };

> > inline void Y::f(X& x)
> > {
> >   x.g(*this);
> > }

> > HTH
> > -cd



Fri, 25 Feb 2005 07:14:35 GMT  
 Cross-referencing classes
Hi Carl,

Yes I see how that works. It still feels weird that the definition of class
Y needs to be split up with class X delcaration in the middle. I should have
also mentioned I like to keep class definitions, even those which are
dependent upon one another, in separate files as well. I don't like header
names like "Both.Class.X.and.Class.Y.h".

And, none of this would be an issue at all with a double-pass compiler. But
this may actually be more a limitation inherent with remaining standard C++
compliant than a matter of MS's choice to use a single-pass compiler.. :)

  /== Peteroid ==\


Quote:


> > Hi Carl,

> > Your example doesn't illustrate what I'm talking about, since it
requires
> > cross-referenced class METHODS. Change X and Y to classes (can
structures
> > have methods?) ,

> struct - class: makes no difference.

> > and add a method to class X (let's call it j( )) and then
> > the question becomes how to use this function in class Y (which is
defined
> > before it)?

> That's precisely what Y::f() does - read again.

> -cd



Fri, 25 Feb 2005 08:25:37 GMT  
 Cross-referencing classes

Quote:
> Hi Carl,

> Yes I see how that works. It still feels weird that the definition of
class
> Y needs to be split up with class X delcaration in the middle. I should
have
> also mentioned I like to keep class definitions, even those which are
> dependent upon one another, in separate files as well. I don't like header
> names like "Both.Class.X.and.Class.Y.h".

> And, none of this would be an issue at all with a double-pass compiler.
But
> this may actually be more a limitation inherent with remaining standard
C++
> compliant than a matter of MS's choice to use a single-pass compiler.. :)

It's 100% necessary for C++ compliance, no matter how many passes the
compiler makes over the source code.  If you want it to work the other way,
use C# or Java :)

-cd



Fri, 25 Feb 2005 09:13:14 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. Compiling of classes with cross references

2. Class Cross Referencing

3. Cross Reference Utility for C Source?

4. C/C++ cross reference tool

5. Cross-reference in include files

6. Cross reference tools for C/C++ under Unix

7. C functions cross-referencing tool

8. Cross references

9. cross reference

10. cross-references in c...

11. C/C++ Cross Reference Utilities - Recommendation

12. Cross Reference Utility for C Source?

 

 
Powered by phpBB® Forum Software