views:

1268

answers:

4

there was a somewhat detailed thread (228684) on how to globally (using extern struct) declare a structure that could be seen in more than 1 c++ file, but I can not figure out exactly how to do it (there was a lot of discussion about do this, do that, maybe do this, try this, etc...).

couuld someone please post a very simple example of how to declare a structure that could be seen in 2 separate c++ files? If I put all my functions in the same file as the main it works fine, but when I try to split the functions out in different files I cannot get it to compile.

Things I am unclear on... Should I typedef the structure? Do I define the structure in a header file and include that header in each c++ source file? Do I need the #ifndef macro in the header file? Do I declare the structure extern in the header?

Thank you

+6  A: 

It's called a header file.

in your header file (call it foo.h)

#ifndef FOO_H
#define FOO_H
class X {
};
#endif

Then, in any C files you have

#include "foo.h"
X x;

For C++ it's more common/preferred to use class, but you can use struct as well. The extern keyword generally refers to variables, not class/struct declarations. You would make a global variable extern in a header file (then declare it not-extern) in one of your .cpp files.

David Nehme
The #ifndef, #define and #endif are to protect you from the fairly common case where you accidentally include the same file twice (usually via some third file)
Tom Leys
I've coded a bit of C just to get familiar with pointers and such, so I can confidently say that my ignorance on C++ is absolute. However, what has always bugged me is: would have been so hard for the compiler to check if a file has been included already and, in that case, avoid including it again?
Juan Pablo Califano
A: 

Here's a little example:

#ifndef __my_header__
#define __my_header__

class my_class
{

};

#endif

The class my_class will be visible in any file that includes this header. I think there is something else to your question, though, but I don't quite see what.

Ben Collins
You should avoid prefix'd __ as it's not standards compliant. __ is reserved for internal compiler usage
JaredPar
bzzzt. That's only for identifiers in the global namespace. Those macros don't appear in the preprocessed sources, and thus don't pollute the global namespace.
Ben Collins
There could be an identifier in the global namespace named __my_header__ defined by the compiler.
John Dibling
+2  A: 

Structures cannot be extern or static. If you want to have a structure used in more than two translation units, put the structure definition into a header:

foo.hpp

struct foo {
    int a;
    int b;
};

Then include that header file into all source files using that struct. Having a struct/class/union defined in multiple source-files is perfectly valid, as long as each one is same defined. You can put a Include Guard around the definition of foo to prevent that foo is included twice into the same sourcefile being compiled. (So, having multiple foo in the same program is valid, but having multiple foo in the same source (note: meaning translation unit) is not valid.) See 3.2 One Definition Rule in the C++ Standard or a Draft.

When you see this:

extern struct foo { int a; int b; } b;

Not the foo is extern, but the b (the object) is extern! It's saying that b is not defined, but merely declared, so you can refer to it.

Johannes Schaub - litb
A: 

If you want a global variable; a single struct accessible from multiple compilation units (C++ files):

/* foo.h */
#ifndef EXAMPLE_FOO_H
#define EXAMPLE_FOO_H

struct foo {
    int a;
    int b;
};

extern struct foo globalFoo;

#endif /* EXAMPLE_FOO_H */

--

/* foo.cpp */
#include "foo.h"

struct foo globalFoo = { 1, 2 };

--

/* bar1.cpp */
#include "foo.h"

int test1()
{
    int c = globalFoo.b; //c is 2
}

--

/* bar2.cpp */
#include "foo.h"

int test2()
{
    int x = globalFoo.a; //x is 1
}

The "struct {}" line in foo.h tells the compiler what struct foo looks like. The "extern struct" line declares a particular struct foo called "globalFoo" with external linkage. (It is possible to combine these two declarations, see @litb's answer.) What this means is that users of globalFoo (bar1/test1 and bar2/test2) will look for the struct elsewhere, they will not have their own seperate copies.

foo.cpp is the special case that defines globalFoo. There can only be one definition of any variable, and in this case foo.cpp has globalFoo's definition. When bar1 and bar2 look for globalFoo "externally," they will find foo.cpp's globalFoo. The name will refer to the same actual struct in all three files.

If the extern hadn't been there, then all three .cpp files would have a line that read "struct foo globalFoo;" (Remember, #include is just copy/paste) That would [attempt to] create three different structs with the same name, resulting in a mess.

Note: The "extern struct foo globalFoo;" line is redundant in foo.cpp's case, but that doesn't matter.

aib