This question already has answers here:
creating classes link error
(2 answers)
Closed 8 years ago.
I'm trying to learn how to make classes in C++ where I use a header file, a .cpp file that contains the class function definitions, and a main .cpp file. Here is what I have (taken from an example)
in class.h
class MyClass
{
public:
void foo();
int bar;
};
in class.cpp
#include "class.h"
using namespace std;
void MyClass::foo()
{
cout<< "test";
}
in main.cpp
#include "class.h"
using namespace std;
int main()
{
MyClass a;
a.foo();
return 0;
}
Compiling the main.cpp results in this error:
[Linker error] C:\:(.text+0x16): undefined reference to `MyClass::foo()'
collect2: ld returned 1 exit status
Do I need to compile the class.cpp or class.h? Am I missing a way of linking class.h with class.cpp? If so how do I link them?
You need to compile the implementation files into object files and link them together. The following is an example for when you are using g++:
g++ -c class.cpp -o class.o
g++ -c main.cpp -o main.o
g++ class.o main.o -o main
./main
In reality, you would add more options like -std=c++11 -O3 -Wall -Wextra -Werror etc.
You can try this on Linux shell using g++
Compile Create object files of main.cpp and class.cpp called main.o and class.o
g++ -c class.cpp
g++ -c main.cpp
Linking the object codes main.o and class.o to create executable file called program
g++ -o program main.o class.o
then run the program executable file
./program
You are likely to be compiling only main.cpp and not class.cpp.
What command are you using to generate the output ?
This should work fine :
g++ class.cpp main.cpp -o class
Its working fine
I tried the code in my Compiler
MyClass.h
#include <iostream>
class MyClass
{
public:
void foo();
int bar;
};
MyClass.cpp
#include "MyClass.h"
using namespace std;
void MyClass::foo()
{
cout<< "test";
}
Main.cpp
#include <iostream>
#include "MyClass.h"
int main(int argc, const char * argv[])
{
MyClass a;
a.foo();
return 0;
}
Ive tried the code in Xcode.
Its working just fine.
Use compiler option -I<dir of .h file> while compiling .cpp file. Compile both the .cpp files
Related
I want to write a shared library and I want to get a compiler/linker error if I forgot to implement some functions.
Consider the following case:
test.h
class Test {
public:
Test();
};
test.cpp
#include "test.h"
main.cpp
#include "test.h"
int main() {
new Test();
}
If I create a library with this command gcc -c -fpic test.cpp && g++ -shared -o libtest.so -Wl,--no-undefined -Wl,--no-allow-shlib-undefined test.o there is no error message, but the library is broken. Is there a way to force the creation of a not broken library?
Edit: adding additional flag, but doesn't change result
These codes have been modified:
test.h :
class Test {
public:
Test();
};
test.cpp :
#include "test.h"
Test::Test(){} // you must implement the constructor
You must have to implement the constructor, and if not, you get an error "undefined reference to `Test::Test()'".
main.cpp :
#include <iostream>
#include "test.h"
using namespace std;
int main(void)
{
Test* t = new Test(); // you must define a pointer
cout << "test* was created: " << t << endl;
delete t;
t = nullptr;
return 0;
}
Now all the code is OK. Then we create a shared-library with the following command:
g++ -shared -o test.so -fPIC test.cpp
Finally, we compile the main.cpp file at the same time as referring to the test.so shared-library and get the exe output, by the command below:
g++ -g main.cpp test.so -o test.exe
I am trying to link a dll with a very simple testing program, but I am getting an error, that I will describe at the end of the post.
frvt11.h - Interface (just relevant code) I need to implement to create my dll
namespace FRVT {
class Interface {
public:
static std::shared_ptr<Interface>
getImplementation();
}
}
implementation.h - Header of my implementation of Inteface
#include "frvt11.h"
namespace FRVT {
class Implementation : public FRVT::Interface {
public:
static std::shared_ptr<Interface>
getImplementation();
}
}
implementation.cpp - My implementation of Interface
UPDATE: change from Implementation::getImplementation to Interface::getImplementation
#include "implementation.h"
using namespace FRVT;
std::shared_ptr<Interface>
Interface::getImplementation() {
std::cout<<"getImplementation";
return std::make_shared<Implementation>();
}
main.cpp
UPDATE: Explicitly indicate the namespace Interface::
#include "frvt11.h"
using namespace FRVT;
int main(){
auto obj = Interface::getImplementation();
return 0;
}
compilation directives
UPDATE: include of -L/dll-directory where are all .h, .cpp and dll
g++ -std=c++11 -c -Wall -Werror -m64 -fPIC implementation.cpp
g++ -std=c++11 -shared -m64 -o libimplementation.so implementation.cpp
g++ -std=c++11 -Wall -m64 -o main main.cpp -L/dll-directory -limplementation
error
UPDATE: Original problem solved
main.cpp: In function 'int main()':
main.cpp:6:34: error: 'getImplementation' was not declared in this scope
auto obj = getImplementation();
How to solve this error? I was expecting that the linker would do the "magic" to say to main.cpp, that the implementation of referred function would be at the dll. What am I doing wrong?
At implementation.cpp I've changed from:
Implementation::getImplementation()
to:
Interface::getImplementation()
At main.cpp I've explicitly indicate the interface, like bellow:
auto obj = Interface::getImplementation();
And finally I've used the -L directive to indicate where was the the generated dll.
I know there are many similar topics but there are equally many unique mistakes that may lead to this problem (so I think). Therefore I ask, after some research.
My problem is that the compiler, GNU GCC, when compiling one file does not see my namespace declared in another file. The IDE (CodeBlocks) evidently does see it as it auto-completes the name of the namespace. I tried to isolate the problem and came up with this:
File main.cpp:
namespace MyName
{
int MyVar;
}
#include "T1.cpp"
int main()
{
return 0;
}
File T1.cpp:
using namespace MyName;
error: 'MyName' is not a name-space name.
In my project I have a header file, say T1.h, and an implementation file T1.cpp — and MyName isn't accessible in either of them.
Any help or guidance would be appreciated.
What's happening is that CodeBlocks is compiling both main.cpp and T1.cpp. Here is what happens when you try to compile each one:
main.cpp:
$ g++ main.cpp
$
T1.cpp
$ g++ T1.cpp
T1.cpp:1:17: error: ‘MyName’ is not a namespace-name
using namespace MyName;
^
T1.cpp:1:23: error: expected namespace-name before ‘;’ token
using namespace MyName;
^
$
T1.cpp, when compiled on it's own, has no knowledge of MyName. To fix this, don't include .cpp files, and put your declarations in header files.
Edit: From what I gather, this may be a better way to organize your example:
T1.h:
namespace MyName {
extern int MyVar;
}
T1.cpp
#include "T1.h"
int MyName::MyVar = 5;
main.cpp
#include "T1.h"
#include <iostream>
using namespace MyName;
int main()
{
std::cout << MyVar << std::endl;
return 0;
}
Now it will compile correctly:
$ g++ -c T1.cpp -o T1.o
$ g++ -c main.cpp -o main.o
$ g++ T1.o main.o
$ ./a.out
5
I made a program to test my knowledge on class but I had some troubles.
foo.h:
#include <iostream>
using namespace std;
class foo
{
private:
int a;
public:
foo();
};
foo.cc:
#include <iostream>
#include "foo.h"
using namespace std;
foo::foo()
{
a = 0;
}
And main.cc:
#include<iostream>
#include "foo.h"
int main()
{
foo a;
return 0;
}
I compiled this with g++ main.cc -o main. Then I got
-bash-4.1$ g++ main.cc -o main
/tmp/cc5Hnes8.o: In function `main':
main.cc:(.text+0x10): undefined reference to `foo::foo()'
collect2: ld returned 1 exit status
I think there should be a really stupid mistake here but I really cannot find it. I've been struggling on this whole night...
Appreciate any help!
You are asking the compiler to not only translate main.cc but also perform the final link to produce the executable main. This second step cannot be done because main.cc references the function foo::foo whose definition is in foo.cc and therefore not available to the compiler. You can do this:
g++ main.cc -c -o main.o
g++ foo.cc -c -o foo.o
g++ main.o foo.o -o main
The -c flag makes the compiler perform translation only, so this separately compiles main.cc and foo.cc and then links the objects together to obtain the executable. In this way, the definition of foo::foo will end up inside foo.o and will be available at link time.
Or, you can just provide both .cc files. This basically does the same thing as the three commands above:
g++ main.cc foo.cc -o main
You should compile all source (.cc in your case) files:
g++ main.cc foo.cc -o main
When you realize the constructor of foo in foo.cc, you should compile it.
use g++ main.cc foo.cc -o main.
I cannot get this simple piece of code to compile without including the TestClass.cpp file explicitly in my main.cpp file. What am I doing wrong? Thanks in advance!
Here is the code:
TestClass.h
#ifndef TESTCLASS_H_
#define TESTCLASS_H_
class TestClass
{
public:
static int foo();
};
#endif
TestClass.cpp
#include "TestClass.h"
int TestClass::foo() { return 42; }
main.cpp
#include <iostream>
#include "TestClass.h"
using namespace std;
int main()
{
cout << TestClass::foo() << endl;
return 0;
}
Here is the error:
g++ main.cpp -o main.app
/tmp/ccCjOhpy.o: In function `main':
main.cpp:(.text+0x18e): undefined reference to `TestClass::foo()'
collect2: ld returned 1 exit status
Include TestClass.cpp into the commandline, so the linker can find the function definition:
g++ main.cpp TestClass.cpp -o main.app
Alternatively, compile each to their own object file, then tell the compiler to link them together (it will forward them to the linker)
g++ -c main.cpp -o main.o
g++ -c TestClass.cpp -o TestClass.o
g++ main.o TestClass.o -o main.app
You're not compiling and linking against TestClass.cpp (where the implementation of foo() is). The compiler is thus complaining that your trying to use an undefined function.