I have main.cpp, MyClass.cpp and MyClass.h files.
main.cpp
#include <iostream>
#include "MyClass.h"
int main(){
MyClass foo(123);
std::cout << foo.getNumber();
}
MyClass.h
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass
{
public:
MyClass(int n);
int getNumber();
private:
int fav_number;
};
#endif // MYCLASS_H
MyClass.cpp
#include "MyClass.h"
MyClass::MyClass(int n) {
fav_number = n;
}
MyClass::getNumber(){
return fav_number;
}
Now this program compiles and works fine as a project in CodeBlocks, but if I try to compile main seperately (not in a project) I get undefined reference to MyClass::MyClass(int). I think it is because in MyClass.h there is no body for the functions as they're in the cpp file.
So my question is: how does this program compile as a project even though MyClass.cpp isn't included anywhere in the main or the header?
When you add your cpp file to IDE it adds it to compile sources.
Depends on your IDE, for example XCode has section compile sources:
If you compile in console with g++, you need to type in console:
g++ main.cpp MyClass.cpp
This means which source files to compile, after that linker should link their main.o MyClass.o files. IDE just do all this stuff by himself.
You compile each .cpp file independently (indeed, if you look at your compiler output, you should see main.o and MyClass.o). The header files simply tell the code that the definitions exist somewhere and after compiling, a linker is used to "link" the two .o files together. It is during the linking stage that the definitions are resolved, so when main.o refers to code in MyClass.o, the linker is what puts these together.
CodeBlocks hides this from you, but its calling out to your compiler and linker to do this. (Actually, if you call gcc with all of your .cpp files, it will call the linker for you too, but this is simply a convenience and you can do it in multiple steps too. If you are using gcc to compile, your linker is usually ld)
You tell it to.
When using an IDE, the list of files in the "project" determines what list of filenames the IDE sends to the compiler, in a build command.
When invoking the build command manually, you have to do that yourself.
For example:
g++ -o myprogram main.cpp MyClass.cpp
Or:
g++ -c main.cpp
g++ -c MyClass.cpp
g++ -o myprogram main.o MyClass.o
Obviously add other flags as needed (include paths etc).
On MyClass.cpp you've forgotten return type specified on its header MyClass.h as follows
int MyClass::getNumber(){
return fav_number;
}
From a terminal console you must pass to the compiler g++ as argument all the files *.cpp which main depends on otherwise you will have an error as follows:
$ g++ main.cpp
/tmp/ccDTbMs5.o: In function `main':
main.cpp:(.text+0x15): undefined reference to `MyClass::MyClass(int)'
main.cpp:(.text+0x21): undefined reference to `MyClass::getNumber()'
collect2: error: ld returned 1 exit status
As you can see the compiler is trying to look for object code that is not found. When you compile main.cpp along with all the cpp files corresponding to the includes on your main. In this manner it will work for you as follows:
$ g++ main.cpp MyClass.cpp -o myprogram
$
$ ./myprogram
123
Option -o change the output program to "myprogram".
More complex situations can be treat using builders such as "Makefile".
In case you do not have the implementation files .cpp for each of your header files .h , you should have instead the binary object code. This should be passed to the g++ accordanly.
$ g++ -c MyClass.cpp
$ g++ -c main.cpp
The previous lines creates MyClass.o and main.o. Notice that the -c is passed to the compiler to indicate that only compilation will be done. Now you can pass the objects to the compiler as follows linking all of then together:
$ g++ -o prog MyClass.o main.o
$ ./prog
123
Related
Seen this post:
How do you compile a C++ program with multiple class files from OS X Terminal?
I see that to compile with gcc a project with a class (with .h and .cpp) is easy as:
g++ [list of all source files] -o [executableName]
And it actually works for me, but when i try to use Clang:
clang++-11 main.cpp Person.hpp Person.cpp -o main
I get:
clang: error: cannot specify -o when generating multiple output files
NOTE: i know how to use Makefile's, but i would like to have a quick way to compile in Clang like in gcc.
If you run clang++-11 main.cpp Person.hpp Person.cpp -o main with the header file, clang notices this and compiles the pre-compiled header "Person.pch", the default -o Person.pch is implied. Meanwhile you want getting yet another output file "main". Thus, clang complains it can't generate multiple output files, -o Person.pch and -o main.
Pre-compiled headers should be compiled separately.
clang++-11 Person.hpp
clang++-11 main.cpp Person.cpp -o main
The first step is not required, if skipped, no pre-compiled headers are used.
This is not actual code i am working on but sample code i had written to understand what i am doing wrong. So i have three files main.cpp, favourite.cpp and favourite.h. I am trying to compile main.cpp but get some weird error.
// main.cpp File
#include <iostream>
#include "favourite.h"
using namespace std;
int main()
{
favNum(12);
}
// favourite.cpp File
#include "favourite.h"
#include <iostream>
using namespace std;
void favNum(int num)
{
cout << "My Favourate number is " << num << endl;
}
// favourite.h File
#ifndef FAVOURITE_H
#define FAVOURITE_H
void favNum(int num);
#endif
This all files are in same folder and i am compiling it normally like g++ main.cpp I am not sure if i need to compile it diffrently as i am using custom header files.
If you say g++ main.cpp and this is your whole command line, the error is a linker error that it can't find favNum, right? In that case, try:
g++ main.cpp favourite.cpp
or split compilation and linking:
g++ -c main.cpp -o main.o
g++ -c favourite.cpp -o favourite.o
g++ main.o favourite.o
Where -c means: Compile only, no linking and -ofilename is required because you want to write the output to two different object files to link them with the last command.
You might also add additional flag, the most important ones are:
-Wall -Wextra -O3
Oh I guess I see the error although you should have included it in your question.
When compiling multiple source files you need to list them all on the GCC command line. Or you can use a Makefile.
So you could do this:
g++ favourite.cpp main.cpp
Or you could write a Makefile like this:
all: program
program: main.o favourite.o
And then just type:
make
I have 3 files to compile with G++, the main file is like this:
//main.cpp
#include "test.hpp"
int main(int argc,char** args) {
//
}
The second file is the header file:
//test.hpp
namespace shared {
class test {
//constructor
test();
};
}
The last file is the code file for test.hpp
//test.cpp
shared::test::test() {
//
}
And I compile using G++ this way:
g++ -c main.cpp test.cpp
However, G++ complains about undefined identifier 'shared' in the file 'test.cpp'. In the command line I already pass in file 'main.cpp', which includes the header file. How to fix this? I only want to have all the '#include's be in main.cpp, and no where else.
Add #include "test.hpp" at the beggining of test.cpp.
Compiler doesn't care about the order of files in the commandline. It only affects the linker.
Please also note, that the usual way of compiling multi-file projects is to compile each of them to different sub-object like so:
g++ main.cpp -o main.o
g++ test.cpp -o test.o
ld main.o test.o -o program[.exe]
This allows you to recompile only the files that really did change. If you think about it for a while, you'll find out that a .cpp file can contain many headers without a problem; however, the compilation time will increase when your headers will start to have many headers included. Forward declarations can help solve those issues, yet with your simple example simple solution will work.
You have to say #include "test.hpp" in your test.cpp file. The namespace declaration has to be known.
Recently I have tried to compile a program in g++ (on Ubuntu). Usually i use Dev-C++ (on Windows) and it works fine there as long as I make a project and put all the necessary files in there.
The error that occurs when compiling the program is:
$filename.cpp: undefined reference to '[Class]::[Class Member Function]'
The files used are as following:
The source code (.cpp) file with the main function.
The header file with the function prototypes.
The .cpp file with the definitions for each function.
Any help will be appreciated.
You probably tried to either compile and link instead of just compiling source files or somehow forgot something.
Variation one (everything in one line; recompiles everything all the time):
g++ -o myexecutable first.cpp second.cpp third.cpp [other dependencies, e.g. -Lboost, -LGL, -LSDL, etc.]
Variation two (step by step; if no -o is provided, gcc will reuse the input file name and just change the extension when not linking; this variation is best used for makefiles; allows you to skip unchanged parts):
g++ -c first.cpp
g++ -c second.cpp
g++ -c third.cpp
g++ -o myexecutable first.o second.o third.o [other dependencies]
Variation three (some placeholders):
Won't list it but the parameters mentioned above might as well take placeholders, e.g. g++ -c *.cpp will compile all cpp files in current directory to o(bject) files of the same name.
Overall you shouldn't worry too much about it unless you really have to work without any IDE. If you're not that proficient with the command line syntax, stick to IDEs first.
The command line of gcc should look like:
g++ -o myprogram class1.cpp class2.cpp class3.cpp main.cpp
Check in which cpp file the missing class member function is defined. You may have not given it to gcc.
You can also check for correct #include tags within filename.cpp. Assume that filename.cpp uses code contained in myclass.h present in the same directory as filename.cpp. Assume that the class that g++ says is undefined is contained in myclass.h and defined in myclass.cpp. So, to correctly include myclass.h within filename.cpp, do the following:
In filename.cpp:
#include <iostream>
#include <myclass.h>
//..source code.
In the makefile:
filename.o: myclass.C myclass.h filename.cpp
g++ -I./ -c filename.cpp -o filename.o
myclass.o: myclass.C myclass.h
g++ -c myclass.C -o myclass.o
In the above, note the use of -I. option when compiling filename.cpp. The -I<directory> asks g++ to include the path following the -I part into the search path. That way myclass.h is correctly included.
In the absence of more information (the source maybe), it is difficult to say with any accuracy where the problem lies. All attempts will be but stabs in the dark.
I assume that you have declared a member function (usually in a .h or .hpp file) but have ommited the respective definition of the member function (usually in a .cpp file).
In c++, it is possible to declare a class like so:
class foo {
void x();
void y();
}
with a cpp file that goes like so
void foo::x() {
do_something()
}
Note, there is no foo::y().
This poses no problem to the compiling/linking process as long as the member function foo::y() is referenced nowhere throughout the compiled code.
I've got three files, add.h, add.cpp and test.cpp
add.h creates a header for a class, and is nothing but skeletons for implementation later.
add.cpp contains the actual code for the class listed in add.h
test.cpp contains the main method and declares an instance of the class in add and uses some of its methods.
However, I'm having trouble compiling it. In add.h, I have #DEFINES to prevent multiple writes of the header, and in add.cpp and test.cpp I have add.h included, but when I attempt to compile using the line
g++ test.cpp -o test
I get an error about undefined references to the class objects and methods in add.h. I've been searching google on how to compile or run this, but so far no help, can StackOverflow help me?
EDIT: Sorry, I should have also included that I did try g++ test.cpp add.cpp -o test and it didn't work either, yielding the same resulting errors.
Compile each file separately, then link:
g++ -Wall -c test.cpp
g++ -Wall -c add.cpp
g++ -o test test.o add.o
Or compile and link all files in one command:
g++ -Wall -o test test.cpp add.cpp
run g++ test.cpp add.cpp -o test
EDIT: copypasted my comment here
You need to understand why your initial approach isn't working. When you reference stuff from add.h header in test.cpp, the compiler looks for definitions, but does not find them, because they are in add.cpp and you did not pass it to the compiler. The compiler can't just guess that it should look for the definitions in the add.cpp file just because you included add.h in test.cpp.
run g++ test.cpp add.cpp -o test
or
g++ -c add.cpp -o add.o
g++ -c test.cpp -o test.o
g++ test.o add.o -o test
the -c flag tells gcc to just compile and not link
the first two steps compile 1 cpp (a compilation unit) in an object file
the last step links those into a single executable
your actual problem comes from the fact that when you compile test.cpp, it refers to some simbols which are undefined.
If you're just compiling (-c flag) that's fine, and the next step is to link with those objects file containing the missing symbols.
You need
g++ test.cpp app.cpp -o myTest
as app.cpp contains code used by test.cpp.