I have heard that we should write the declarations in a header file and the definition in a source file, with both the source and the header having the same name. And then just include the header in the source.
Here is an example myFile.h:
void printer (void);
Here is the implementation of printer in myFile.cpp:
#include "myFile.h"
#include <iostream>
using namespace std;
void printer ()
{
cout<< "I am a printer";
}
Here is my main.cpp:
#include "myFile.h"
int main ()
{
printer();
return 0;
}
Now when I run the program, I get the expected error: undefined reference to printer. But when I see code on github or other projects I see that usually they have included the header file and not the source file. I also tried using the header guards ifndef but still the same error came.
The main program is successfully compiled if:
If i include myFIle.cpp in myFile.h
If i include just myFile.cpp in main
What I the general practice while doing the same?
You should include your myFile.cpp in the linking process:
g++ myFile.cpp main.cpp
The error message undefined reference to printer is actual a linker error, not a compiler error.
Explanation
If you use only g++ main.cpp compiler won't create code from myFile.cpp. He knows that there should be a function with the signature void printer(void), but he doesn't now yet where this function is. He completely ignores this fact, since you can provide pre-compiled object files ("myFile.o") and link those later:
g++ myFile.cpp -c # compile myFile.cpp
g++ main.cpp -c # compile myFile.cpp
g++ myFile.o main.o # link both files together.
-c will tell g++ only to compile the files, but not link them together to an executable. This is done by a linker (g++ will probably call ld in your configuration). The linker will create an executable which contains all needed libraries like libc++ and actual code.
IDE remarks
If you use an IDE make sure that all needed files are included in the project. This includes all header and source files and linkage options for additional libraries.
When yourself define a header file and want to include it, you should enclose it "", such as :
#include "myFile.h"
#include "myFile.h" // would be better.
It seems you forgot the " surrounding the include.
You should use
#include "myFile.h"
or
#include <myFile.h>
the later is rather for system libraries. Both forms differ in the way the search the file.
You find more details on
http://msdn.microsoft.com/en-us/library/36k2cdd4%28v=vs.71%29.aspx
Related
Let's say I have 3 files:
Test.hh
#ifndef TEST_HH_
#define TEST_HH_
class Test
{
int test() const;
};
#endif /* TEST_HH_ */
Test.cc:
#include "Test.hh"
int Test::test() const
{
return 0;
}
main.cc:
#include "Test.cc"
int main()
{
return 0;
}
It does not compile (rather does not link), I understand why, I defined Test::test() in multiple translation units (in main.cc that includes Test.cc and in Test.cc):
g++ -Wall -g -std=c++17 -c main.cc -o main.o
g++ -Wall -g -std=c++17 -c Test.cc -o Test.o
g++ -o bin main.o Test.o
Test.o: In function `Test::test()':
Test.cc:12: multiple definition of `Test::test()'
main.o:Test.cc:12: first defined here
collect2: error: ld returned 1 exit status
Edit: This is NOT my issue, my issue is that with a seemingly identical situation, in a bigger project, the previous example produces a binary (i.e. compiles and links) when, as far as I understand it, it shouldn't. I will now describe the real case with a bit more details and how the problem suddenly arised when previously it was working fine (when it shouldn't have).
--
I am currently working on a large project (~2500 files), and while trying to use the "Test" class above, I ended up having a lot of "multiple definitions" errors at link time. To translate it to our example, it's like I had another class doing this:
OtherClass.hh
#include "Test.hh" // including or using forward declaration led to the same results
//class Test; forward declaration
class OtherClass
{
// Some stuff, whatever
};
I ended up finding that Test.cc was included in another source file (main.cc in my very simplified exemple though it was in another "someClass.cc" in my actual project). After including the header instead of the source, it compiled again. What's more surprising is that other classes had been using Test.hh the same way until then without any problems.
Since I was really surprised, I ended up doing a grep on all my files and found that another 2 source files had included other sources files as well.
WhateverClass.cc
#include "Test2.cc"
YetAnotherClass.cc
#include "Test3.cc"
All those files are compiled and contain function definitions yet the linker does not complain. I tried doing a compilation from scratch and it still worked.
So my question is: Why does this compile even though some source files include others and all of them are compiled ? And why did it suddenly stop working even though I just included the header of one of those source files just like other classes had been doing ? Is there a kind of "undefined behavior" for cases like this ?
If it is of any help, my project is using CMake. I tried compiling with ninja or Make with the same results.
I had a similar question before. So, here's what I learned- never include source file. Only include header files. Your error comes from including a source (.cc) file in your main. You should include Test.hh instead. Declare all your classes and functions in header, include that header to all the source files where the definitions and the calls are.
I have a template class of a binary tree, tree.tpp and tree.h. I have done a test with the class but I can't compile it
#include <cstdlib>
#include <iostream>
#include "arbolbinario.h"
using namespace std;
int main(int argc, char** argv) {
ArbolBinario<int> pila(45);
return 0;
}
And I'm having the following error when I do: g++ -c -o ./tree.o ./tree.tpp -I ./tree.h
g++: warning: ./tree.tpp: linker input file unused because linking not done
(I'm working with netbeans)
.tpp is not one of the file endings recognized by g++, see its documentation.
Therefore g++ assumes that you want the file to be passed to the linker directly. But since you used the -c flag, which indicates that you want g++ to only compile, but not invoke the linker, you get that error message.
The solution is to tell g++ what kind of file it is that you are passing it explicitly:
g++ -c -o ./tree.o -x c++ ./tree.tpp -I ./tree.h
or, better, rename your C++ source file use one of the common file endings for C++ source files, e.g. .cpp, .cc, .cxx, etc. That would result in less trouble with build tools and less confusion for others looking at your project.
As noted in the question comments -I ./tree.h also is clearly wrong, but not the cause of this particular error (and probably it just doesn't belong there at all).
However:
If your .tpp contains the implementation of methods of a class template, then you should not rename it (.tpp is appropriate in that case), but you also should not compile it as translation unit at all. That means it should not appear in any g++ command.
.tpp files implementing a template classes methods need to be included in the .h file with the class template definition, instead. Otherwise you will get linker errors later when you try to link your files, see Why can templates only be implemented in the header file?.
The -c flag tells GCC to only compile the input source files, not to do any linking.
If you want the compiler to link the object files into an executable binary, you need to remove the -c flag.
I am trying to compile a c++ code with a third party library using g++ as a compiler.
My main.cpp needs to include the header file core.hpp while the core.hpp needs to include cvdef.h whereas cvdef.h need to include interface.h.
The paths for these three headers in the include statements are as follows:
#include "opencv2/core.hpp"
#include "opencv2/core/cvdef.h"
#include "opencv2/core/hal/interface.h"
See file structure in image below.
When I compile my main.cpp it finds the core.hpp. The core.hpp, however, cannot seems to find cvdef.h as it is looking within the 'core'-folder for the 'opencv2'-folder (which is a level below).
Without changing the paths in the include statement, how would I go about this?
My current compile statement using g++ under Windows is:
g++ main.cpp -o main
It seems that OpenCV2 wants to look for the header files in standard locations.
You can add to the list of standard locations by using the -I (upper-case i) option, specifying the path to add.
In your case you should be able to do it with
g++ main.cpp -o main -Iopencv2/core
In the following code, I am trying to call a dummy function written in C++ (using C++ header files like ap_fixed.h, ap_int.h) from a C function. The code runs fine when I compile with g++. But when I use gcc for compiling test.c, it throws an error because I have included a C++ header file which is a valid error.
Is there any workaround to compile using gcc? I have read from some posts that it is not a good practice to merge C/C++ code in this manner. Please enlighten me if there are any serious repurcussions of working with a large C codebase and doing similar stuff.
Thanks
Header File: testcplusplus.h
#include "ap_fixed.h"
#include "ap_int.h"
#ifdef __cplusplus
extern "C" {
#endif
void print_cplusplus();
#ifdef __cplusplus
}
#endif
testcplusplus.cc
#include <iostream>
#include "testcplusplus.h"
void print_cplusplus() {
ap_ufixed<10, 5,AP_RND_INF,AP_SAT > Var1 = 22.96875;
std::cout << Var1 << std::endl;
}
test.c
#include <stdio.h>
#include "testcplusplus.h"
int main() {
print_cplusplus();
}
Commands Used:
g++ -c -o testcplusplus.o testcplusplus.cc
ar rvs libtest.a testcplusplus.o
gcc -o test test.c -L. -ltest
Error:
In file included from ap_fixed.h:21:0,
from testcplusplus.h:1,
from test.c:2:
ap_int.h:21:2: error: #error C++ is required to include this header file
The problem here is that the C++ header ap_fixed.h is included from the C program test.c (indirectly via testcplusplus.h).
The solution is to remove the include of headers "ap_fixed.h"
and "ap_int.h" from testcplusplus.h and include them directly from testcplusplus.cpp. The C program doesn't need to know about these anyway, only the C++ wrapper uses them directly.
In a larger example it might be appropriate to split testcplusplus.h into two headers: one that contains only declarations of the external interface you are presenting to the C environment, and another containing the rest - declarations needed internally in the C++ implementation and any required includes.
Once you have done this, you will still face linking errors because the executable that is produced will contain references to symbols from the C++ runtime libraries, plus any other libraries that your C++ code uses. To solve this, add -l directives when compiling the final executable, eg:
gcc -o test test.c -L. -ltest -lstdc++
You do not need to include ap_int.h and ap_fixed.h at this point, as the declaration of the print_cplusplus function does not need those definitions.
Rather, include them in testcplusplus.c, so the C compiler can only see the C compatible interface of the C++ code.
I used the C-library RS232 in my C++ code to control an Arduino Uno board. In my main.cpp, I got:
#include "rs232.h"
because in the rs232.h header file, they already have:
#ifdef __cplusplus
extern "C" {
#endif
In one folder, I have:
main.cpp
rs232.h
rs232.c
stdafx.h
stdafx.cpp
and I use cygwin to compile so that the code could be used for Linux:
g++ main.cpp
but I got errors with "...undefined reference to '_OpenComport'" and similar to all C functions that I called from my main.cpp.
Can anyone tell me how to include the C header file in C++? Or is it that I used the wrong command for g++?
You need to pass all source files to the compiler, like so
g++ -o demo.exe main.cpp rs232.c stdafx.cpp
Alternatively, compile parts into a library, and separate compile and link steps.