Using global variables defined in a header file - c++

First of all I know this isnt "correct." However, I like to test things out and I have run into this problem that if I create a global variable in the header file and declare it extern in the main.cpp file, I can use it(Note that I did not include the class header on this example). However, if I actually try to do the same thing, the only difference being including the class header, I get an error.
(error: ld returned 1 exit status).
I wonder why this happens?
Code as requested:
Main.cpp:
#include <iostream>
#include "albino.h"
using namespace std;
extern int iVar;
int main()
{
cout << iVar << endl;
}
albino.h:
#ifndef ALBINO_H
#define ALBINO_H
int iVar = 10;
class albino
{
public:
albino();
};
#endif // ALBINO_H
The albino.cpp doesnt have anything.
ERROR: ||error: ld returned 1 exit status|

I think you are doing it the wrong way around.
You can define a global variable only once; but you can declare it many times, wherever you want to use it.
That means int i = 0; should only be existing once, so _not in the header, but in exactly one cpp file (doesn't matter for the compiler which one, only for humans that try to find it); and extern int i; can be in the header so it is repeated everywhere.
See also How do I use extern to share variables between source files?

Related

Global Constants in .h included in multiple c++ project

I want to run a small simulation in c++.
To keep everything nice and readable I seperate each thing (like all the sdl stuff, all the main sim stuff, ...) into it's own .h file.
I have some variables that I want all files to know, but when I #include them in more then one file other the g++ compliler sees it as a redefinition.
I understand why he does this, but this still leaves me with my wish to have one file where all important variables and constants for each run are defined and known to all other files, to easily find and change them when running my simulation.
So my Question here: Is there a good workaround to achieve that or something similar?
You can put the declarations for all the globals in a header and then define them in a source file and then you will be able to use those global variables in any other source file by just including the header as shown below:
header.h
#ifndef MYHEADER_H
#define MYHEADER_H
//declaration for all the global variables
extern int i;
extern double p;
#endif
source.cpp
#include "header.h"
//definitions for all the globals declared inside header.h
int i = 0;
double p = 34;
main.cpp
#include <iostream>
#include "header.h" //include the header to use globals
int main()
{
std::cout << i <<std::endl;//prints 0
std::cout<< p << std::endl;//prints 34
return 0;
}
Working demo
Mark them as extern in the header and have one translation unit that defines them.
Note: Without LTO (link time optimization) this will seriously slow down your simulation.

using extern keyword for user defined types in c++

I want to use extern keyword for user defined types. This means I've declared object in one file and defined it in other file. I've read that extern keyword is used to declare the variable without defining it. extern keyword is useful when program is split into multiple source files and global variable needs to be used by each of them. Please correct me If I am wrong somewhere.
Here is the programs I've written but unfortunately I am doing something wrong or missing something so I am getting compiler errors.
Prog1.cpp
#include <iostream>
using std::cout;
class test
{
public:
void fun();
};
void test::fun()
{
cout<<"fun() in test\n";
}
test t;
Prog2.cpp
#include <iostream>
using std::cout;
extern test t;
int main()
{
t.fun();
}
Now when I compile these 2 using
g++ -o prog1.cpp prog2.cpp
compiler gives me following errors in prog2.cpp
error: 'test' does not name a type
error: 't' was not declared in this scope
Please help me to know what I've done wrong here.
extern tells the compiler that the definition of t is somewhere else, but the compiler still needs the defintiion of test, as you're using t.fun() to compile Prog2.cpp.
So the solution is, write test.h where you define the class, and then define test t in Prog2.cpp as usual. Include test.h in your Prog2.cpp so that it may know the definition of test. Then build it.
test.h:
#include <iostream>
using std::cout;
class test //definition of test
{
public:
void fun()
{
cout<<"fun() in test\n";
}
};
Prog1.cpp:
#include "test.h"
test t; //definition of t
Prog2.cpp:
#include <iostream>
#include "test.h"
using std::cout;
extern test t; //the definition of t is somewhere else (in some .o)
//and the definition of test is in test.h
int main()
{
t.fun();
}
Now your code should compile and link.
Note that the definition of t is needed by the linker at link-time, so it will search for it in other .o files, but the definition of test is needed by the compiler, at compile-time.
Now it should be obvious that you can put the extern test t; in the header itself so that you dont have to write it in every .cpp file where you want to use the object defined in Prog1.cpp file (which is turned into Prog1.o by the compiler).
Put the extern keyword in the header, not the cpp file. It is the job of the header to tell the compiler there is an externally defined object somewhere.
For example:
program.h (mostly declarations)
struct UserDefinedType
{
void do_stuff();
};
// declare your global object in the header
// so that the compiler knows its name when
// compiling sources that can not otherwise see
// the object
extern UserDefinedType global_udt;
program.cpp (mostly definitions)
#include "program.h"
// define the member functions here
void UserDefinedType::do_stuff()
{
}
// define the global object here
UserDefinedType global_udt;
main.cpp (use the definitions that have been declared in the header)
#include "program.h" // tells the compiler about global_udt
int main()
{
// call the global object that is defined
// in a different source file (program.cpp)
global_udt.do_stuff();
}
NOTE: If we didn't declare the object global_udt in the header file then main.cpp would not know of its existence and the compiler would complain if we tried to use it.
So the header needs to only declare the object and not define it hence the extern keyword is needed.
Please note that a variable declared outside the class scope is a variable with external linkage(if not explicitly used the static keyword) or with internal linkage(if the static keyword is put in the left of the variable type), extern is necessary if you want to use it in multiple files.
Suppose this file is called MyVariable.h
int myNumber = 0; // Initialization of the variable myNumber, external linkage
static int myStaticNumber; // Initialization of the variable myStaticNumber, internal linkage(only the file in which it's declared)
And this file is OtherFile.cpp
extern int myNumber; // Not a initialization because it's already initialized in another file, works fine
extern int myStaticNumber; // ERROR, this variable has internal linkage!!
You may wonder why myStaticNumber was initialized and not just declared, that occurs because static variables are initialized to their default values by default.

Circular include statements leading to link error

I have a large project (20+ files) but I managed to set up this small example which recreates my problem. Essentially I have one file (A.cpp) including a second file (B.cpp), but that second file needs several of the variables and functions from the first file. Observe:
A.h:
#ifndef _A_H_
#define _A_H_
static void foo(int _something);
#endif // #ifndef _A_H_
A.cpp:
#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;
static void foo(int _something)
{
cout << _something << "\n";
}
int main(int argc, char *argv[])
{
B *b;
foo ( 123 ); // So we don't get that pesky defined-not-used warning
b = new B ();
b->display ( 123 );
}
B.h:
#ifndef _B_H_
#define _B_H_
#include "A.h"
class B
{
public:
B();
~B();
void display ( int x );
};
#endif // #ifndef _B_H_
B.cpp:
#include "B.h"
void B::display ( int x )
{
foo ( x );
}
And I am compiling it like so, g++ -Wall A.cpp B.cpp -o main but then I get this error:
A.h:3:13: warning: ‘void foo(int)’ used but never defined [enabled by default]
/tmp/ccFwfZa6.o: In function `main':
A.cpp:(.text+0x54): undefined reference to `B::B()'
/tmp/ccM8SNBK.o: In function `B::display(int)':
B.cpp:(.text+0xd): undefined reference to `foo(int)'
collect2: ld returned 1 exit status
I can tell it's a link error, but I can't tell why I am getting that error.
EDIT:
In my original code I am still getting an error, this time it's about the multiple definition of an integer, here is the error I am getting:
B.o:(.bss+0x4): multiple definition of `some_var'
A.o:(.bss+0x4034): first defined here
collect2: error: ld returned 1 exit status
make: *** [main] Error 1
and I am creating the variable some_var like so
A.h:
#ifndef _A_H_
#define _A_H_
static void foo(int _something);
int some_var;
#endif // #ifndef _A_H_
How is it possible that some_var would get defined more than once when I have those conditional guards?
You have no B::B() body at all. Add one, and don't forget about destructor.
Also, remove static from foo().
The problem now is that each source file that #includes a.h gets a definition of int some_var;. In general, variables should be declared in headers and defined in one source file. So in your header you need
extern int some_var;
and in one source file (presumably a.cpp)
int some_var;
Thanks to Pete Becker I figured out the problem, and it stemmed mostly from a lack of understanding of all things C/C++.
extern statements are not meant to only be used in header files referencing other header files (ie. in "B.h" writing extern int a where a is defined in "A.c") but also in the original header files (in this case "A.h")
I thought, incorrectly, that a definition needed an equals sign (ie. int a = 1) whereas int a is also a definition. I was, thus, defining my variable in "A.h" when I should have been declaring it like so extern int a in "A.h".
After fixing the above 2, I kept getting undefined reference to a (I literally thought the compiler and linker were taking the piss). I was searching for int a=... in "A.cpp" and as clear as day it was being defined. Turns out this definition was inside a function, and therefore was never being defined.
If all else fails, edit your source files in a trivial way (ie. delete a word and type it again) to force a compilation) as I find changing the header files does not always result in full compilations.

Apple Mach-O linker command failed with exit code 1

I'm using Xcode to build a C++ project.
But I don't understand the error message:
"Apple Mach-O linker command failed with exit code 1"
I found that #include is the reason.
I have two .cpp file which include a same .h file. If I remove #include of one, it will be build successfully.
Other header files are fine expect the header file described above. I already used "ifndef".
#ifndef include guards only work at the level of the translation unit (usually a single source file).
If you define the same object twice in two translation units, that won't be fixed by include guards but the linker will complain bitterly when you try to combine the two object files into a single executable.
I suspect your situation is akin to:
hdr.h:
#ifndef HDR_H
#define HDR_H
void rc(void);
int xyzzy;
#endif
prog1.c:
#include "hdr.h"
#include "hdr.h"
int main (void) { rc(); return xyzzy; }
prog2.c:
#include "hdr.h"
void rc(void) { xyzzy = 0; }
In a situation like that, the include guard will prevent the header being included twice in prog1.c but it will still be included in both prog1.c and prog2.c, meaning that each will have a copy of xyzzy.
When you link them together, the linker will not like that.
The solution is to not define things in headers but to merely declare them there, leaving the definition for a C file:
hdr.h:
#ifndef HDR_H
#define HDR_H
int rc(void);
extern int xyzzy; // declare, not define
#endif
prog1.c:
#include "hdr.h"
#include "hdr.h"
int main (void) { rc(); return xyzzy; }
prog2.c:
#include "hdr.h"
int xyzzy; // define
int rc(void) { xyzzy = 0; }
Declarations are things like function prototypes, extern variables, typedefs and so on (simplistically, things that declare something exists without actually creating an "object").
Definition are things that create "objects", like non-extern variables and so on.
You need to track down what "object" is being defined twice (the linker output should have something like doubly-defined symbol 'xyzzy') and then make sure it's not defined in the header.

Why are my C++ includes defining vars multiple times?

I understand that pre-processor commands are an important part of header files to prevent vars and classes from being defined more than once.
I have been running into issues with my vars being defined multiple times - even with pre-processor wrappers. Here is a sample project that is experiencing compiler errors:
Header:
// TestInclude.h
#ifndef TESTINCLUDE_H_
#define TESTINCLUDE_H_
int myInt;
#endif /*TESTINCLUDE_H_*/
C++:
// TestInclude.cpp
#include <iostream>
#include "IncludeMe.h"
#include "TestInclude.h"
int main( int argc, char* args[] )
{
std::cin >> myInt;
IncludeMe thisClass;
std::cin >> myInt;
}
Header:
// IncludeMe.h
#ifndef INCLUDEME_H_
#define INCLUDEME_H_
class IncludeMe
{
private:
int privateInt;
public:
IncludeMe();
};
#endif /*INCLUDEME_H_*/
C++:
// IncludeMe.cpp
#include <iostream>
#include "IncludeMe.h"
#include "TestInclude.h"
IncludeMe::IncludeMe()
{
std::cout << "myInt: " << myInt;
}
Then I compile like this:
Makefile:
all:
g++ -g -o TestInclude TestInclude.cpp IncludeMe.cpp
And I get the following error:
/tmp/ccrcNqqO.o: In function `IncludeMe':
/home/quakkels/Projects/c++/TestInclude/IncludeMe.cpp:6: multiple definition of `myInt'
/tmp/ccgo6dVT.o:/home/quakkels/Projects/c++/TestInclude/TestInclude.cpp:7: first defined here
collect2: ld returned 1 exit status
make: *** [all] Error 1
Why am I getting this error when I'm using pre-processor conditionals in my header files?
Include guards do not protect against multiple definitions. They only protect against infinite recursive inclusion. (You can of course include the same header in multiple translation units!)
You should never have object definitions* in the header; only declarations:
header.hpp:
extern int a;
file.cpp:
#include "header.hpp"
int a = 12;
*) You can have class definitions in a header file, as well as inline functions and class member functions.
You should use extern int myInt; in header files and only write int myInt; in the single .cpp file where you want to define it.
Some projects use a preprocessor macro like "IN_FOO_CPP" to make that happen automatically with #ifdefs.