Using extern keyword for custom types in C ++
I want to use a keyword extern
for custom types. This means that I have declared an object in one file and defined it in another file. I read that the extern keyword is used to declare a variable without defining it. The extern keyword is useful when a program is split into multiple source files and a global variable must be used by each one. Please correct me if I am wrong somewhere.
Here are the programs I wrote, but unfortunately I am doing something wrong or missing something, so I get 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
the compiler is giving me the following errors in prog2.cpp
error: 'test' does not name a type
error: 't' was not declared in this scope
Please help me find out what I did wrong here.
source to share
extern
tells the compiler that the definition t
is somewhere else, but the compiler still needs the definition test
as you are using t.fun()
to compile Prog2.cpp
.
So there is a solution, write test.h
where you define the class and then define test t
in Prog2.cpp
as usual. Include test.h
in Prog2.cpp
so he knows the definition 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();
}
Your code should now compile and link.
Note that the definition is t
needed by the linker at link time, so it will look for it in other files .o
, but the definition is test
needed by the compiler when compiling, time.
It should now be obvious what you can put extern test t;
in the header, so you don't need to write it in every file .cpp
where you want to use the object defined in the file Prog1.cpp
(which turned into the Prog1.o
compiler).
source to share
Put the extern keyword in the header, not in the cpp file. The job of the header is to tell the compiler that there is an external 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 were 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 have not declared an object global_udt
in the header file, then main.cpp will not know about its existence, and the compiler will complain if we tried to use it.
So the header only needs to declare the object and not define it, so the extern keyword is required.
source to share
Note that a variable declared outside the class is a variable with external linkage (unless the static keyword is explicitly used) or with internal linkage (if the static keyword is placed to the left of the variable type), extern is necessary if you want to use it in multiple files.
Let's assume 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 declared)
And this file OtherFile.cpp
extern int myNumber; // Not a initialization because it already initialized in another file, works fine
extern int myStaticNumber; // ERROR, this variable has internal linkage!!
You may be wondering why myStaticNumber was initialized and not just declared, which is because, by default, static variables are initialized to default values.