Reputation: 43
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.
Upvotes: 0
Views: 118
Reputation: 6255
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 include
s 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.
Upvotes: 2
Reputation: 337
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.
Upvotes: 2