duplictate global extern

is there a big disadvantage when my two cpp's needs to access the extern variables on a header file.

foo.h
1
2
3
4
 
#pragma once
extern int foobar;
void func();

bar.cpp
1
2
3
4
int foobar = 5;
void func() {
std::cout >> foobar;
}

bar2.cpp
1
2
3
4
int foobar = 5; //declared as global 2nd times
void func() {
std::cout << foobar;
}

and how can i access extern in 2 cpp's
Last edited on
Do you really need to use globals?
Do you really need to use extern?

I think namespaces may help you if you want to keep some kind of 'global' scope in your code.
http://www.cplusplus.com/doc/tutorial/namespaces/
@mutexe has given the best advice - "just say no" - no to globals, the use of globals is the root of all evil.

However, if you're just trying to understand what the problem is...

You don't just have 2 declarations, you have - and this is a problem - 2 definitions

You can declare the same thing numerous times, but you can define it once and only once. A definition is a highlander, there can be only one :-)

To illustrate the difference between the two, here's a quote from Meyer's Effective C++:

A declaration tells compilers about the name and type of something, but it omits certain details. These are
declarations:

1
2
3
4
5
 extern int x;                                  // object declaration 
 std::size_t numDigits (int number);             // function declaration 
 class Widget;                                  // class declaration 
 template<typename T>             
 class GraphNode;                // template declaration                  


A definition provides compilers with the details a declaration omits. For an object, the definition is where compilers
set aside memory for the object. For a function or a function template, the definition provides the code body. For a
class or a class template, the definition lists the members of the class or template:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 int x;                                           // object definition 

 std::size_t numDigits (int number)                // function definition . 
{  //  (This function returns the number of digits in its parameter.)
   std::size_t digitsSoFar = 1;                   
   while  ((number /= 10)  != 0) ++digitsSoFar; 
   return digitsSoFar; 
 } 

 class Widget  {                                   // class definition 
 public: 
   Widget (); 
   ~Widget (); 
    ... 
 }; 

 template<typename T>                             // template definition 
 class GraphNode  {             
 public: 
   GraphNode (); 
   ~GraphNode (); 
    ... 
 }; 


To summarise:

foo.h
extern int foobar; // declaration

bar.cpp
int foobar = 5; // definition

bar2.cpp
#include "foo.h"
1
2
3
4
...
// foobar already defined in bar.cpp, remember to link bar.o
int barbar = foobar; // use
foobar = 5; // use 
Global variables are frowned upon these days because global state can be difficult to debug. Avoid it where you can.

In answer to your question though, you should only declare foobar in one file, otherwise the extern is useless.

in the example I would code bar2.cpp as follows..
 
foobar = 5;


now there is one global variable declared in foo.h, defined in bar.cpp and referenced as an external from bar2.cpp [extern just means external from this translation unit(cpp), ie; it's defined in another cpp file. ]

having multiple copies of the global contradicts the whole point of extern.
okay i will read it. please keep watching on this thread. and this is my code
attack.h
1
2
3
4
5
6
7
8
9
10
#ifndef ATTACK_H_INCLUDED
#define ATTACK_H_INCLUDED

extern int enemy_hp, damage, hp, experience, level, defence;
void battleSystem();
void battleCommand(char&);
void attack();
void messageWinning();
void messageLosing();
#endif 

and then the others 2 declare globals to use the externs
i created my own namespace on a header file, but it seems that the header file can only be included once
it seems that the header file can only be included once

They should be "multi-includable". You have other errors.
Last edited on
@keskiverto
attack.obj already defined
something like that, i cant make it appear again, coz i created new program

and is it okay to include header file within a header file?

foo.h
1
2
3
4
5
6
7
8
 
#ifndef FOO_H_INCLUDED
#define FOO_H_INLUCDED 
#include "conio.h"
#include <iostream>
#include <string>
//declaration
#endif 




#ifndef ATTACK_H_INCLUDED
#define ATTACK_H_INCLUDED

extern int enemy_hp, damage, hp, experience, level, defence;
void battleSystem();
void battleCommand(char&);
void attack();
void messageWinning();
void messageLosing();
#endif


Have you considered using classes?
(and you really should stay away from extern unless you're trying to call into C code)
Last edited on
1>foobarsystem.obj : error LNK2005: "int status::level" (?level@status@@3HA) already defined in Foobar Attack.obj
1>foobarsystem.obj : error LNK2005: "int status::exp" (?exp@status@@3HA) already defined in Foobar Attack.obj
1>foobarsystem.obj : error LNK2005: "int status::damage" (?damage@status@@3HA) already defined in Foobar Attack.obj
1>foobarsystem.obj : error LNK2005: "int status::player_hp" (?player_hp@status@@3HA) already defined in Foobar Attack.obj
1>foobarsystem.obj : error LNK2005: "int status::enemy_hp" (?enemy_hp@status@@3HA) already defined in Foobar Attack.obj
1>foobarsystem.obj : error LNK2005: "int status::defence" (?defence@status@@3HA) already defined in Foobar Attack.obj

here, i made the error appear
is it okay to include header file within a header file?

Lets see ... This is how MSVS12's header file "iostream" starts:
1
2
3
4
5
6
7
// iostream standard header for Microsoft
#pragma once
#ifndef _IOSTREAM_
#define _IOSTREAM_
#ifndef RC_INVOKED
#include <istream>

The header clearly includes another header at line 6. You have been including the iostream in your programs and that has been "okay"? Yes.

Furthermore, when you have a header that contains something like this:
1
2
3
4
class Foo {
  std::string bar;
  // other code
}

The std::string has to be defined before the definition of Foo. Either those, who include this header, will include "string" before it, or this header includes the "string". The latter is not only "okay" but much more logical and convenient. The "include" directives are handled by the preprocessor and that little helper tool does operate recursively.
@keskiverto
They should be "multi-includable". You have other errors.

it is not multi-includable

EDIT: but when i make the member variables of namespace into static theres no problem
Last edited on
This is valid, because the header has proper inclusion guards:
1
2
3
4
5
6
7
8
#include <iostream>
#include <iostream>

int main() {
  std::cout << "hello";
  return 0;
}
#include <iostream> 


These (B+C) are valid (program) too:
B.cpp
1
2
3
4
5
6
7
8
#include <iostream>
void foo();

int main() {
  std::cout << "hello";
  foo();
  return 0;
}

C.cpp
1
2
3
4
#include <iostream>
void foo() {
  std::cout << " world";
}


Your linker errors are due to multiple compilation units providing definition for same symbol. The very same problem that you had at the start of this thread.
Lorence30, can you tell me what you think the extern keyword does, and why you think you should be using it?
And can you tell me if you are using an OO approach or not?

Cheers.
when i make the member variables of namespace into static theres no problem

There is a different problem. Static is not "global":
http://stackoverflow.com/questions/7837190/c-c-global-vs-static-global
@mutexe
any variable that declared as extern will be accesible in any file. but it should be defined first in cpp. extern is like a prototype and defining it is like a definition of prototype.
EDIT: i havent learned oop much yet. im just practicing file scopes
Last edited on
@keskiverto thanks i get it all now
any variable that declared as extern will be accesible in any file. but it should be defined first in cpp.
extern is like a prototype and defining it is like a definition of prototype.

I would not use word "any". The latter part is closer to target.

These are declarations. They introduce identifiers (names) with type. They are enough for code in this compilation unit to refer to them, but the referring binary code will be merely a stub that the linker replaces with call to actual implementation during linking:
1
2
extern double foo;
int bar( std::string );

Only the lines of code in the current compilation unit that are after these declarations can use these identifiers.

These are definitions (implementations). They can be in only one compilation unit that will be linked to the final binary.
1
2
3
4
double foo;
int bar( std::string ) {
  // code
}


These are local definitions. They cannot be declared, referred to, nor linked to in other compilation units:
1
2
3
4
5
6
static double gaz;
namespace {
  int bar() {
    // code
  }
}

To us the namespace appears nameless, but it is unique and separate from nameless namespaces in other compilation units.
Topic archived. No new replies allowed.