I have created two basic .cpp files. First one has just one line of code:
int var=10; , and the second one is this:
#include <iostream>
using namespace std;
int main(){
cout<<var;
return 0;
}
I compile my code using gcc -o myprogram file1.cpp file2.cpp & I always get this message:
error: ‘var’ was not declared in this scope
13 | cout<<var;
Does anyone know how to solve this?
If "var" is a one-off, then simply add an extern:
#include <iostream>
using namespace std;
extern int var;
int main(){
cout<<var;
return 0;
}
If your "first .cpp" grows, and you start adding things other modules will want to use, then you'll probably want to:
Define one or more classes
Create a header file for your class definition(s)
Every translation unit must contain a declaration of every symbol it uses. On the other hand, every symbol must have a definition in exactly one translation unit (unless it's explicitly or implicitly inline; then multiple translation units can have definitions as long as they're all the same).
The usual way to do this is to put the declarations for things in a header file, which you then #include into multiple translation units, while putting their definitions in a .cpp file that forms the main body of the translation unit.
In this particular case, you need a declaration of var in the translation unit that contains main. You could put it in a header that gets #included into file1.cpp; i.e.:
file2.hpp:
#ifndef FILE1_HPP
#define FILE1_HPP
extern int var;
#endif
file2.cpp:
#include "file2.hpp"
int var;
file1.cpp:
#include "file2.hpp"
#include <iostream>
int main() {
std::cout << var;
}
Or you just put it into that translation unit manually; i.e.
#include <iostream>
extern int var;
int main()
{
std::cout << var;
}
Either approach is exactly the same from the compiler's point of view (the preprocessor just does text replacement), but the latter tends to be much more difficult for humans to deal with, so you should probably avoid it in general.
Basically the problem was that I used gcc -o myprogram learn.cpp help.cpp instead of g++ -o myprogram learn.cpp help.cpp to compile. Gcc compiler is used for .c files and g++ for .cpp files
Related
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.
I'm trying to import variables from a file that are used in a class in other file and ultimately import that to yet another file and compile.
Let me show what the reproduction of the problem looks like:
arrayFile.hpp
int arr[] = {
1,2,6,5,4,3
};
classFile.hpp
#include <iostream>
using namespace std;
#include "arrayFile.hpp"
class MyClass{
private:
int v1;
public:
MyClass();
void setV(int v);
int getV();
int funcM();
};
classFile.cpp
#include <iostream>
using namespace std;
#include "classFile.hpp"
MyClass::MyClass(){};
void MyClass::setV(int v){
v1 = v;
}
int MyClass::getV(){
return v1;
}
int MyClass::funcM(){
return v1*arr[0];
}
mainfile.cpp
#include <iostream>
using namespace std;
#include "classFolder/classFile.hpp"
// #include "classFolder/arrayFile.hpp"
// should i include this?
int main(){
MyClass c;
c.setV(3);
cout<<c.funcM()<<endl;
cout<<arr[0]<<'*'<<c.getV()<<endl;
}
The objective is to acess the array from both the classFile.cpp and mainfile.cpp, but I'm not managing to do this.
If I don't include arrayFile.cpp in mainfile.cpp:
/tmp/cce4ZHbp.o:(.data+0x0): multiple definition of `arr'
/tmp/ccmsYdmt.o:(.data+0x0): first defined here
If I do:
In file included from mainfile.cpp:5:0:
classFolder/arrayFile.hpp:1:9: error: redefinition of ‘int arr []’
int arr[] = {
^
In file included from classFolder/classFile.hpp:3:0,
from mainfile.cpp:4:
classFolder/arrayFile.hpp:1:5: note: ‘int arr [6]’ previously defined here
int arr[] = {
^
I've was able to get the compiler to tell me arr[] was undefined too, but am unable to reproduce this error.
What am I doing wrong?
The real issue I'm facing requires me to import an array and a struct to a class, and this class is imported to yet another bigger class, this last class is finally used by main. This is my best at reproducing it. I don't know how to fix this.
You should not include arrayFile.hpp inside your classFile.hpp. Include it only in classFile.cpp. Also, in mainfile.cpp (before main function) add line
extern int arr[];
This line tells the compiles that array of type int called "arr" will be defined in some other cpp file that will be linked together with mainfile.cpp.
Compile your program like this:
g++ -std=c++11 -c main.cpp classFile.cpp
g++ -std=c++11 main.o classFile.o
./a.out
First line compiles your files individually (creating main.o and classFile.o files)
Second line links them together creating one executable file (a.out)
Third line runs the executable file
Since adding new files makes this compilation process complicated, I suggest using a Makefile.
Broadly, it is not a good idea to define variables in a header file - assuming said header file will be included by multiple source files.
When you compile your project, the preprocessor handles "#include" statements by literally placing the content of the included header file in the file including it.
E.g.:
// foo.h
#ifndef FOO_H
#define FOO_H
typedef int myInt;
#endif
.
// main.cpp
#include "foo.h"
int main( int argc, char* argv[] )
{
return 0;
}
.
// preprocessor output
typedef int myInt;
int main( int argc, char* argv[] )
{
return 0;
}
This is a simplification - but good enough for illustrative purpose.
So what's happening in your example?
arrayFile.hpp is included by classFile.hpp which is included by classFile.cpp and mainfile.cpp. It may be helpful to consider the include-tree:
arrayFile.hpp
|
classFile.hpp
/ \
classFile.cpp mainfile.cpp
Think about what I said RE: replacing includes with the included file content and see if you don't agree when I say that classFile.cpp and mainfile.cpp both end up with a definition of your arr array.
What happens next when you're compiling your project? The compiler compiles your source code - specifically, the preprocessor output - to object files. E.g. the preprocessed classFile.cpp becomes classFile.o and the preprocessed mainfile.cpp becomes mainfile.o.
Finally, object files (or the libraries they are archived into) are linked to form your executable.
When the linker tries to link classFile.o and mainfile.o it will discover that both have arr defined in them. Thus you get your multiple definition linker error - not a compiler error.
So: if a header file is included - directly or indirectly - by multiple source files, you'll run into linker errors if the header file defines variables. This is why, it is standard practice to declare variables in header files and define them in one source file.
Hope that helps.
I'm just testing out how extern works (using MSVC) and I cannot get it to work, no matter what I do:
// Test.h
int externalint = 10
// Main.cpp
void main()
{
extern int externalint;
std::cout << externalint << std::endl;
std::cin.ignore();
}
This results in a linking error, even though I defined it in the header. I do not wish to include the header because the way I read it says it can be in another translation unit and does not need to be included. Am I wrong with the way I am reading it or did I write something incorrectly? If I include the header, it works, as it should, even without the extern declaration.
Header files are usually not translation units but meant to be included by them. That's why header files usually do not "define" variables, since this would lead to multiple definition errors when the header file is included by different translation units (thereby re-defining the variable again and again).
That's where "extern" comes into place, since this is for just "declaring" a variable without "defining" it. "extern" means "will be defined in some other translation unit".
So the usual way is:
// Test.h
extern int externalint; // just declares externalint
// Test.cpp
int externalint = 10; // defines externalint
// main.cpp
#include "Test.h" // importing the declaration of "externalint" defined elsewhere
int main() {
std::cout << externalint << std::endl;
}
Header files are not typically translation units.
Put the definition in a Test.cpp file.
int externalInteger = 10;
Put your main function in Main.cpp file.
#include <iostream>
int main()
{
extern int externalInteger;
std::cout << externalInteger << std::endl;
std::cin.ignore();
}
Compile and link.
g++ -c Test.cpp
g++ -c Main.cpp
g++ Main.o Test.o
For MS, use cl.exe as the compiler instead of g++.
First ask yourself why would you use such a thing as extern. And then you will understand how to use it.
Imagine you would like a piece of code to be called in different programs.
Once from console application and once from an external program.
So you will write Test.cpp.
Now you can use it at console app using main() function and once you build it together with the external program you can use it there too.
Both will use the externalint value of 10 and as long as you update this Test library in both projects like through git. You would have the identical behaviour in both the console application and the external program.
Where is the Test.h you ask?
There you go:
The Test.cpp will be compiled separately from your Main.cpp but you would like to use the variables and functions from your Test.cpp. How does the compiler know what functions are there?
You will let him know.
You simply create an interface -> Test.h.
And then you will include it in your Main.cpp
#include "Test.h"
Example of interface:
//Test.h
int externalint = 10;
But, what if you have more .cpp files interested in this interface?
Then it will be duplicate and it will not compile. Because you cannot initialize the same variable twice.
Luckily you can declare it and announce that the initialization will be done in one of the .cpp files.
// Test.h
extern int externint;
// Test.cpp
int externint = 10;
1) I know a non-const variable is external linkage by default (it's like it's been declared as external more or less) but i don't understand why can't i define a global variable such as int glbl_a in header
//test.h
#ifndef TEST_H
#define TEST_H
int glbl_a=0; //wrong -> "multiple definition of `glbl_a`"
static int st_glbl_a=1; //ok to initialize it in header!
extern int ext_glbl_a; //ok to declare it and define it in test.cpp
#endif
//test.cpp
#include "test.h"
using namespace std;
//st_glbl_a=22; i could use st_glbl_a but it wouldn't affect st_glbl_a in main cause of 'static'
int ext_glbl_a=2; //definition of external gloabal non-const variable
//main.cpp
#include <iostream>
#include "test.h"
using namespace std;
extern int glbl_a; //declaration of glbl_a external
int main(){
cout<<glbl_a;
}
the working version for this program is the one in which I define int glbl_a=0; in test.cpp only and declare extern int glbl_a; in main before using it in output (definition in test.h is just commented, that is there's nothing about glbl_a).
2)the working version doesn't work anymore if I group all definitions/declaretions into a namespace spread onto test.cpp and test.h (MyNamespace) cause of int glbl_a in test.cpp:
//test.h
#ifndef TEST_H
#define TEST_H
namespace MyNamespace{
//extern int glbl_a;
}
#endif
//test.cpp
#include "test.h"
using namespace std;
namespace MyNamespace{
int glbl_a=0;
}
//main.cpp
#include <iostream>
#include "test.h"
using namespace std;
int main(){
cout<<MyNamespace::glbl_a; //wrong -> "'glbl_a' is not a member of 'MyNaspace'"
}
it would work only if I de-comment declaration in test.h, but why?
Problem 1
Including a header effectively pastes the included file into the including file, producing one large file that is then compiled (and, typically, promptly deleted). This means that every including file now has its very own glbl_a. The compiler is happy, but when the linker attempts to put everything together, it finds many equally valid pretenders to the name glbl_a. The linker hates this and doesn't even try to figure out what you're trying to do. It simply spits out an error message and asks that you fix the problem.
Problem 2
test.cpp and main.cpp are different translation units. They compile to produce different, completely independent objects. Neither can see what's in the other, so the fact that MyNamespace::glbl_a exists in test.cpp is lost on main.cpp. When main.cpp is compiled, the compiler builds a list of identifiers declared in the file constructed from main.cpp and all of its included headers. MyNamespace::glbl_ais never declared as of when it is first used (or after for that matter) so the compiler spits out an error message.
Uncommenting the declaration in test.h means the compiler will find MyNamespace::glbl_a in main.cpp and will allow it's use. Since MyNamespace::glbl_a is defined in test.cpp the linker can find one-and-only-one MyNamespace::glbl_a and can successfully link.
extern does not allocate storage. Instead it is a promise to the compiler that the variable being declared will be fully defined and allocated somewhere else, maybe later in the file or in another file. The variable exists, somewhere, and compilation can continue. The linker will call you out as a liar if it cannot find a definition.
More details here: How does the compilation/linking process work?
More on extern: When to use extern in C++ and Storage class specifiers
headers will be included by other files (more than one) thus if you define in header, it will be in each translation unit thus lead to "multiple definition"
I have 4 files:
shared.h
main.cpp
something.h
something.cpp
shared.h:
#ifndef SHARED_H
#define SHARED_H
int* sth;
#endif
something.h:
#ifndef SOMETHING_H
#define SOMETHING_H
class foo
{
public:
void printVar();
};
#endif
something.cpp:
#include <iostream>
#include "something.h"
#include "shared.h"
using namespace std;
void foo::printVar()
{
cout<<"Foo: "<<*sth<<endl;
};
main.cpp:
#include <cstdlib>
#include <iostream>
#include "shared.h"
#include "something.h"
using namespace std;
int main(int argc, char *argv[])
{
sth=new int(32);
foo x;
cout<<"Main: "<<*sth<<endl;
x.printVar();
system("PAUSE");
return EXIT_SUCCESS;
}
Compiler returns multipe definition of *sth;
I added static modifier to the *sth and it compiles, but crashes. I changed the printings to print the adresses of pointer and I had program returned:
Main: 0x3e0f20
Foo: 0
Why is the foo's pointer not assigned? I want to assign it only once in main and then share in other files... How can I do this? Is it something with extern modifier?
Thanx for any replies.
In shared.h you want to say:
extern int* sth;
to promise the compiler that sth exists somewhere.
Then in one (and only one) of the .cpp files you need to write:
int* sth;
To make it actually exists. In general you probably want to read about the difference between declaration and definition. As a rule of thumb you only want to declare things in header files, not define them.
When you wrote static previously you said that a variable with the same name exists in every file, but is "local" to each, i.e. the sth in main.cpp won't be the same as the sth in something.cpp.
Yes, use extern. Put extern int* sth; in the header, and then in one of the source files put int* sth;.
extern tells the compiler and linker that the actual variable/function definition is in another compilation unit (i.e. another source file).
You need to mark sth as extern in the header to make it a declaration, and provide a definition for it in one of the cpp files. Otherwise, the variable is declared in each compilation unit where the header is included, which is not the effect you are looking for.
P.S. I assume that you know why global variables are not good, right?
"I have 4 files".
Let me stop you right there. I agree that you have four files, but that's not really relevant. You have two translation units. A translation unit is the quantum of text that is fed into your compiler. Your translation units, let's call them MAIN and SOMETHING, consist of the result of preprocessing your files main.cpp and something.cpp, respectively.
After preprocessing, each of your translation units includes a line int *sth; This line declares and defines the variable sth.
The one-definition-rule requires that you have, in your entire program, exactly one (not more, not fewer) definition of sth. In order to accomplish this, you must have exactly one source-code line int *sth; in exactly one translation unit, and as many extern int *sth; as you require.
In your case, I would put int *sth; in MAIN and extern int *sth; in SOMETHING. Additionally, you can have as many extra copies of extern int *sth; as you feel like -- they won't hurt anything.
Now, back to your four files. You should put extern int *sth; in shared.h. This means that MAIN and SOMETHING will both have an extern line in them. You should also put int *sth; in main.cpp, so that MAIN will have the definition.
And there you are: MAIN and SOMETHING both have extern lines, so they are both referring to the same variable. MAIN also has a definition. so the sth variable has exactly one of those.
Aside: Why does static int *sth; in shared.h do the wrong thing?
Because each of the two translation units see their own static declaration. A static declaration reduces the linkage of the declared name to that single translation unit.
You don't want to make it a static global as that will create a local sth in every translation unit and you are only allocating it in one. This is why it crashed in Foo::printVar as in that scope it was an uninitialized pointer.
You want to declare it as extern int* sth; in the shared header then put int* sth; before main or in at least one place before it's used.
Actually, if you really need a globally accessible object, allocated on the heap, and you want to share it then it may be better as extern std::shared_ptr<int> sth;. Define it as std::shared_ptr<int> sth; the same way in one of the CPP files and call std::make_shared to allocate it. This way deallocating the memory will be handled automatically when the last object that uses it goes out of scope.