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.
Related
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
I have 2 files each containing a static int variable which has the same name :
test-1.cpp:
#include "test-2.cpp"
static int a;
int main() {
}
test-2.cpp:
static int a;
void fonction() {
}
When I compile with cl test-1.cpp on command line, I get this error:
test-1.cpp(3): error C2086: 'int a' : redefinition
Because you include test2.cpp into test-1.cpp the actual code seen by the compiler is this:
static int a;
void fonction() {
}
static int a;
int main() {
}
Hence the redefinition.
The #include preprocessor command includes the file textually.
What you actually want is have both files test-1.cpp and test-2.cpp included into the Visual Studio project.
You want this:
test-1.cpp
#include "test-2.h"
static int a;
int main() {
fonction();
}
test-2.cpp
#include "test-2.h"
static int a;
void fonction() {
}
test-2.h
void fonction();
Of course, you are #including test-2.cpp in test-1.cpp. It's as if you have only one file. If you remove the #include and do this command
cl test-1.cpp test-2.cpp
then it will work.
This whole area is called separate compilation and it's something that newbies struggle with (it's also not often taught very well). Because of separate compilation you should never include one cpp file in another cpp file. Instead you should hand both files to the compiler so they can be compiled separately.
If one cpp file needs to know what's defined in another cpp file, then create a header file with declarations of what's in the second cpp file and include that in the first cpp file.
In this line;
#include "test-2.cpp"
you tell the preprocessor to put the content of test-2.cpp into test-1.cpp. Hence you define static int a; twice. This is not allowed. To fix this, remove the #include.
Note that you need to carefully distinguish between declarations (which can occur many times) and definitions (which can occur only once). Have a look at this thread for more info.
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 3 files in a Visual Studio project: test.cpp, date.cpp and main.cpp -
test.cpp:
int g() { return 0; }
date.cpp:
/*totally empty*/
main.cpp:
#include "test.cpp"
#include "date.cpp"
int main() { return g(); }
I understand that defining functions in a header file leads to violation of One-Definition Rule if header file is called multiple times. But here, I am calling it only once from only one file/translation unit. Why is it still throwing LNK2005?
You should not include test.cpp and date.cpp. Instead, you should write test.h and date.h, and include it:
test.h
int g();
date.h
// Contains prototypes for functions inside date.cpp
main.cpp
#include "test.h"
#include "date.h"
int main() { return g(); }
You are including "test.cpp" in "main.cpp" - this is most likely wrong, as Visual Studio will ALSO compile "test.cpp" as a separate file, and then link "test.obj" with "main.obj" (those are the files generated by the compiler) into "main.exe". When it then finds "g()" in both "test.obj" and "main.obj", it says "Huh? Why have you got two of these" (or, in linker terms "multiple defined symbols").
The solution is to have a "test.h" that declared void g(); and then use that to include into "main.cpp".
Since test.cpp is in the VS Project, it will be compiled and lined in along with main.cpp causing the multiple definitions - unless you take special measure to prevent that from happening, like removing test.cpp from the project or setting it to be "Excluded from Build".
If you rename temp.cpp to test.h you get two benefits:
VS will not automatically compile a .h when it's in a project, since it assumes that the file is intended to be included from other files instead of being stand-alone compiled.
it will be less confusing to programmers about the intended use of the files
Today I had an interview there they asked me can we include .c file to a source file?
I said yes. Because few years back I saw the same in some project where they have include .c file. But just now I was trying the same.
abc.c
#include<stdio.h>
void abc()
{ printf("From ABC() \n"); }
main.c
#include<stdio.h>
#include "abc.c"
int main()
{ void abc();
return 0;
}
Getting an error:
D:\Embedded\...\abc.c :- multiple definition of 'abc'
Where is it going wrong?
I wrote an abc.h file (the body of abc.h is { extern void abc(void); }),
and included the file in abc.c (commenting out #include abc.c). Worked fine.
Do it as follows:
abc.c:
#include <stdio.h>
void abc()
{printf("From ABC() \n");}
main.c:
#include<stdio.h>
#include "abc.c"
int main()
{
abc();
return 0;
}
(no need for the header file)
Then, to compile, you'd only compile main.c. Do not attempt to compile both abc.c and main.c, because then you'd have the abc() function defined twice.
You need to understand that #include is basically "copy-paste", nothing more. If you tell it #include "abc.c", it will simply take the contents of abc.c, and "paste" them in your main.c file. Therefore, using the above for main.c, after the preprocessor processes it, your main.c will look like this (I'm ignoring the #include <stdio.h>s):
#include<stdio.h>
#include <stdio.h>
void abc()
{printf("From ABC() \n");}
int main()
{
abc();
return 0;
}
which is a valid program.
That said you should generally not do this; you should compile all your .c files separately and only then link them together.
Including C files is perfectly valid as long as you do not try to compile the included C file by itself and then link it together with the object file from the C file which included the other file.
If you do so you'll have the same symbol (usually a function) defined in two files which will result in the errors you posted.
If you have multiple source files you usually do not include them but compile them separately. The linker then merges the object files into a single executable (or library).
You can include file with any extension.
In your program, you had re-defined void abc(); in main (). instead just put statement abc ();
You can include anything you like to, the preprocessor doesn't care about the file extensions. It's only some tradition to name the headers ".h" and the source files ".c" or ".cpp".
You only have to be sure, that after compiling the whole project you don't run into linker problems (e.g. giving both "abc.c" and "main.c" to the compiler would result in multiple definitions of your function).