header file question on linking error.

I include the same header file in 2 cpp files and get an link error for sure.
The header file defined only a namespace and an int.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//header.h
#ifndef HEADER
#define HEADER
namespace Mine{
  int a=0;
}
#endif

//a.cpp
#include "header.h"

//b.cpp
#include "header.h"
int main(){}

g++ a.cpp b.cpp
linking error: multiple definition of `Mine::a'

So, why for STL library, it is possible to #include<iostream>, then use "cout" in different cpp files and no linking error? such like the following is perfect fine in STL, why???

1
2
3
4
5
6
7
8
//a.cpp
#include <iostream>
using std::cout;

//b.cpp
#include <iostream>
using std::cout;
int main(){}


why working with STL, there is no linking error? what's the difference of my header file and STL's <iostream>
Thanks.
Last edited on
STL is short for Standard Template Library and what you meant was the standard library or possibly IOstream.

And in answer to your question, this is what cout is defined as and this is why.
extern ostream cout;

See the extern keyword? That's what lets this work.

-Albatross
Last edited on
So do you mean, if i want to use same global variables in different cpp files, then the only way is to use "extern" in each cpp file?
Thanks.
No... there's always another way... but I'd use extern in this case.

You will need (unless I'm low on caffeine) to have that variable non-extern in one of the files, though, so you know.

-Albatross
sure, i think i may need to write a header file (h.h) and declare "extern int a;" in that header file.
Then i need to create one cpp (a.cpp) file which defines "int a=100".
then all other cpp files which need to use the variable "a", will #include"h.h", and link to a.cpp, right?
Thanks.
I like to think of it this way.

You know how you have function prototypes and function bodies?

1
2
3
4
5
6
int myfunction(); // prototype

int myfunction()  // has a body
{
  return 0;
}


The prototype just tells the compiler "this function exists somewhere", but doesn't actually give the actual function. Whereas the function body is the whole function.

Every function can have one and only one body, and only in 1 source file. If you have multiple function bodies in multiple cpp files, the linker will give you an error because it doesn't know which body to use for the function.


Variables are the same way:

1
2
3
extern int var; // variable "prototype"

int var;  // variable "body" 


The extern keyword tells the compiler "this variable exists somewhere" but doesn't actually create the variable. Much like how the function prototype doesn't actually define a function.

The 'normal' non-extern variable (the "body") actually creates a variable, allocates space for it, and ties that variable name with that space in memory.

Just as with functions, if you have two global variables with the same name in two seperate cpp files, the linker will complain because you're creating two seperate variables, each with their own memory. And the linker doesn't know which variable you intend to use.


EDIT:

That said, global variables are horrendous and you should avoid using them, of course.
Last edited on
Thanks for your detailed explanation. Sure I understand this topic and all your explanation make perfect sense to me.
But if i have to use global variables and don't what the globals to pollute the namespace, then what do i do?
i try the following but it didn't work.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//header.h
namespace My{
  extern int a;
}

//a.cpp
int a=10;

//g.cpp
#include "header.h"
#include <iostream>
void g(){
  //My::a=1;
}

//main.cpp
#include "header.h"
#include <iostream>
using std::cout;
using namespace My;
int main(){
  cout<<a<<"\n";
}


error:
main.cpp : undefined reference to `My::a'
g.cpp: undefined reference to `My::a'
oh, I see,
i need to change a.cpp to
namespace My{
int a=10;
}
Topic archived. No new replies allowed.