tags:

views:

221

answers:

5
...
#include "test1.h"

int main(..)
{
    count << aaa <<endl;
}

aaa is defined in test1.h,and I didn't use extern keyword,but still can reference aaa.

So I doubt is extern really necessary?

+1  A: 

If aaa is not defined in another compilation unit you don't need extern, otherwise you do.

Otávio Décio
+3  A: 

If your test1.h has the definition of aaa and you wanted to include the header file into more than one translation unit you will run into multiple definition error, unless aaa is constant. Better you define the aaa in a cpp file and add extern definition in header file that could be added to other files as header.

Thumb rule for having variable and constant in header file

 extern int a ;//Data declarations
 const float pi = 3.141593 ;//Constant definitions

Since constant have internal linkage in c++ any constant that is defined in a translation unit will not be visible to other translation unit, but it is not the case for variable they have external linkage i.e., they are visible to other translation unit. Putting the definition of a variable in a header, that is shared in other translation unit would lead to multiple definition of a variable, leading to multiple definition error.

yesraaj
+2  A: 

In that case, extern is not necessary. Extern is needed when the symbol is declared in another compilation unit.

When you use the #include preprocessing directive, the included file is copied out in place of the directive. In this case you don't need extern because the compiler already know aaa.

Opera
How do you define **compilation unit** ?
httpinterpret
@httpinterpret every cpp file along with all the included headers will form a compilation/translation units, cppfile == compilation unit. Header files are just a mechanism to reduce typing, look at your project as a group of cpp files with include"header.h" replaced with actual content of header file. Compilation unit is just object files that see after compilation, linking all those files will give you the exe/dll.
yesraaj
+6  A: 

I've found the best way to organise your data is to follow two simple rules:

  • Only declare things in header files.
  • Define things in C (or cpp, but I'll just use C here for simplicity) files.

By declare, I mean notify the compiler that things exist, but don't allocate storage for them. This includes typedef, struct, extern and so on.

By define, I generally mean "allocate space for", like int and so on.

If you have a line like:

int aaa;

in a header file, every compilation unit (basically defined as an input stream to the compiler - the C file along with everything it brings in with #include, recursively) will get its own copy. That's going to cause problems if you link two object files together that have the same symbol defined (except under certain limited circumstances like const).

A better way to do this is to define that aaa variable in one of your C files and then put:

extern int aaa;

in your header file.

Note that if your header file is only included in one C file, this isn't a problem. But, in that case, I probably wouldn't even have a header file. Header files are, in my opinion, only for sharing things between compilation units.

paxdiablo
Can you elaborate the case you mentioned that "if you link two object files together that have the same symbol defined"? How can `const` fix the problem? –
httpinterpret
`extern int aaa;` is not a definition. it's a declaration. Also, `struct foo { int j };` is a definition which is obviously okay in header files. It pays off to use the correct terminology and have read the one definition rule.
sellibitze
@sellibitze ,I'm aware of this difference.I'm asking why `const` can fixed the problem mentioned by @paxdiablo
httpinterpret
@httpinterpret constants in C++ have internal linkage i.e, visible to only one cpp file, so you would add definition of constant in header file.
yesraaj
Which one of the cpps exactly?Since there may be many cpps that include the header file.
httpinterpret
Generally, in the .cpp relative to the .h (or .hpp) in which it's declared, but YMMV, as usual.
Matteo Italia
@http, where it goes depends on where it makes sense. If you have a (for example) database source file and aaa is something belonging to that, you would expect `int aaa` in db.cpp and `extern int aaa` in db.h. That's because every compilation unit using the db stuff would include that header and link with the db.o object file made from db.cpp.
paxdiablo
@httpinterpret: whichever includes the header file. Each translation unit that does so has its very own internal-linkage constant in this case.
sellibitze
+1  A: 

extern has its uses. But it mainly involves "global variables" which are frowned upon. The main idea behind extern is to declare things with external linkage. As such it's kind of the opposite of static. But external linkage is in many cases the default linkage so you don't need extern in those cases. Another use of extern is: It can turn definitions into declarations. Examples:

extern int i;  // Declaration of i with external linkage
               // (only tells the compiler about the existence of i)

int i;         // Definition of i with external linkage
               // (actually reserves memory, should not be in a header file)

const int f = 3; // Definition of f with internal linkage (due to const)
                 // (This applies to C++ only, not C. In C f would have
                 // external linkage.) In C++ it's perfectly fine to put
                 // somethibng like this into a header file.

extern const int g; // Declaration of g with external linkage
                    // could be placed into a header file

extern const int g = 3; // Definition of g with external linkage
                        // Not supposed to be in a header file

static int t; // Definition of t with internal linkage.
              // may appear anywhere. Every translation unit that
              // has a line like this has its very own t object.

You see, it's rather complicated. There are two orthogonal concepts: Linkage (external vs internal) and the matter of declaration vs definition. The extern keyword can affect both. With respect to linkage it's the opposite of static. But the meaning of static is also overloaded and -- depending on the context -- does or does not control linkage. The other thing it does is to control the life-time of objects ("static life-time"). But at global scope all variables already have a static life-time and some people thought it would be a good idea to recycle the keyword for controlling linkage (this is me just guessing).

Linkage basically is a property of an object or function declared/defined at "namespace scope". If it has internal linkage, it won't be directly accessible by name from other translation units. If it has external linkage, there shall be only one definition across all translation units (with exceptions, see one-definition-rule).

sellibitze