Jump to content


struct in multiple files


10 replies to this topic

#1 thebigT

    New Member

  • Members
  • PipPip
  • 18 posts

Posted 02 December 2010 - 08:59 AM

I am an amateur programmer updating a very amateur file structure I've been using for awhile and have run into some difficulties. Up until this point I've had all my code in multiple headers which I #included in a single source file. For convenience all my structs were defined all together in one of these headers. I am now trying to organise my code into paired source and headers and have spread the struct definitions out into the headers relevant to the code that references them. However some structs are fairly generic and are used broadly throughout the program. An example would be a vector struct. I want this struct defined in a header and then able to be 'seen' throughout the code. It seems that #including the header that contains its definition is not enough. If it is just a pointer to the struct in a function prototype it seems to also need a declaration in that header to make the compiler happy. If the vector struct is nested within another struct definition then it seems to need the vector struct redefined in that header. That's ridiculous! Is this correct? Am I going about this the right way? I am using MS Visual Studio Express C++

#2 Sol_HSA

    Senior Member

  • Members
  • PipPipPipPip
  • 510 posts
  • LocationNowhere whenever

Posted 02 December 2010 - 09:06 AM

First off, you can use more than one #include line, so if you have something that's needed everywhere, just put it in a separate include file and include that from either all the header files that need it.

To avoid issues with multiply-included files, you can use the common include guards:

#ifndef THISHEADER
#define THISHEADER

... the header stuff here ...

#endif
that way, if the file gets included several times (from various header files, for instance), the contents will only get used once. the THISHEADER has to be unique for every header file; a common way is to name it HEADERFILE_H for headerfile.h and OTHERFILE_H for otherfile.h etc.

This is the easy way to do it. More preferable ways include source-side include guards, forward declarations in case the data structure is only used via a pointer, and preferably never including from include files, but those really become issues only when your project grows so large you start to worry about build times..
http://iki.fi/sol - my schtuphh

#3 .oisyn

    DevMaster Staff

  • Moderators
  • 1842 posts

Posted 02 December 2010 - 01:31 PM

I think his problem has more to do with circular dependencies

// A.h
struct A
{
    B * ptr;
};

// B.h
struct B
{
    A * a;
};

Of course you could include A.h from B.h, and include B.h from A.h, but if you include A.h, it in turn includes B.h, and there you have a struct definition of B which nees A but which isn't defined at that point.

The solution is, only include what you actually need. The fact of the matter is, A doesn't need the definition of B, and neither does B need the definition of A. Actual definitions are only needed when accessing their members or when the compiler needs to know their size (which is if you use such a struct as a member of another struct). In above example, you only needs pointers. And all pointers are represented in the same way, so the only thing the compiler needs is that there exists an A when you're using a pointer of A.

So, solution:
// A.h
struct B; // declaration of B, the compiler now knows that B exists, but does not know what it contains.

struct A
{
    B * ptr;
};

// B.h
struct A;

struct B
{
    A * a;
};
It now turns out that neither A nor B needs to include the other header.

That said:

Quote

If the vector struct is nested within another struct definition then it seems to need the vector struct redefined in that header. That's ridiculous! Is this correct?
If you actually mean structs defined within other structs, then you have a problem. As these structs are members, you'll need their encompassing struct definition:
// A.h
struct A
{
    struct NestedA { };

    B::NestedB * ptr;
};

// B.h
struct B
{
    struct NestedB { };

    A::NestedA * ptr;
};
Ok, now what? You can't predeclare B in A because you'll need B's definition in order to access B::NestedB. Basically, you're screwed. This is an unsolvable problem in C++*, and you should avoid these kinds of designs.

* Well, not literally unsolvable, you can apply some template trickery and make use of the two-phase name lookup paradigm to delay the lookup of the nested members until the actual use of the type at which point their both fully defined, but I don't recommend it.
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.

#4 Reedbeta

    DevMaster Staff

  • Administrators
  • 5306 posts
  • LocationBellevue, WA

Posted 02 December 2010 - 06:02 PM

Sol_HSA said:

To avoid issues with multiply-included files, you can use the common include guards:

Please, please, just use #pragma once... :)
reedbeta.com - developer blog, OpenGL demos, and other projects

#5 SyntaxError

    Valued Member

  • Members
  • PipPipPip
  • 139 posts

Posted 02 December 2010 - 08:58 PM

Reedbeta said:

Please, please, just use #pragma once... ;)


I might be wrong but I was under the impression that #pragma once wasn't technically standard. Not that it's a big deal since it seems to be supported a lot.

#6 Reedbeta

    DevMaster Staff

  • Administrators
  • 5306 posts
  • LocationBellevue, WA

Posted 02 December 2010 - 09:00 PM

It's quite widely supported and if it isn't part of the standard it ought to be, as it's obviously better than #include guards when avalable. :yes:
reedbeta.com - developer blog, OpenGL demos, and other projects

#7 thebigT

    New Member

  • Members
  • PipPip
  • 18 posts

Posted 03 December 2010 - 03:35 AM

That's a great help thanks guys.

#8 Sol_HSA

    Senior Member

  • Members
  • PipPipPipPip
  • 510 posts
  • LocationNowhere whenever

Posted 03 December 2010 - 07:52 AM

Reedbeta said:

Please, please, just use #pragma once... ;)
I was certain someone would find something to whine about, hence the last paragraph.

But yeah, I think include guards plus #pragma once is a better solution than external include guards. Will work everywhere and where the pragma is supported, faster compiles.
http://iki.fi/sol - my schtuphh

#9 .oisyn

    DevMaster Staff

  • Moderators
  • 1842 posts

Posted 03 December 2010 - 03:53 PM

I have never actually seen benchmarks between regular guards and #pragma once, but I thought I read somewhere that some compilers simply recognized the standard include guards and acted as if a #pragma once is in that header (or more specificially it doesn't reparse it when that macro is still defined when it's reincluded).

Reedbeta said:

It's quite widely supported and if it isn't part of the standard it ought to be, as it's obviously better than #include guards when avalable. :yes:
Since it's a #pragma directive it's by definition not in the standard :)
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.

#10 poita

    Senior Member

  • Members
  • PipPipPipPip
  • 322 posts

Posted 06 December 2010 - 09:04 AM

.oisyn said:

I have never actually seen benchmarks between regular guards and #pragma once, but I thought I read somewhere that some compilers simply recognized the standard include guards and acted as if a #pragma once is in that header (or more specificially it doesn't reparse it when that macro is still defined when it's reincluded).

I'd be very surprised if any major compilers didn't do this.
Homepage: http://poita.org

#11 genix

    New Member

  • Members
  • Pip
  • 1 posts

Posted 28 January 2011 - 07:05 AM

Hay guys,
heeso is here.I have read this post and also visited the above link.It contains valuable information.I will use this information in future.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users