This question already has answers here:
Separating class code into a header and cpp file
(8 answers)
Closed 5 months ago.
I don't know how to add functions of a class outside its scope to it, use them in another class and then compile it.
MyMain.cpp
#include"MyClass.cpp"
int main(){
MyClass myClass;
myClass.run();
}
MyClass.cpp
#ifndef MYCLASS_CPP
#define MYCLASS_CPP
#include<iostream>
class MyClass {
private:
void usage();
public:
void run();
};
void MyClass::usage(){
std::cout << "usage called" << std::endl;
}
void MyClass::run(){
usage();
}
#endif
I try to compile it with:
g++ MyMain.cpp MyClass.cpp -o main
With that I get the following error message:
/usr/bin/ld: /tmp/ccN7GfOD.o: in function `MyClass::usage()':
MyClass.cpp:(.text+0x0): multiple definition of `MyClass::usage()'; /tmp/ccLhxS6v.o:MyMain.cpp:(.text+0x0): first defined here
/usr/bin/ld: /tmp/ccN7GfOD.o: in function `MyClass::run()':
MyClass.cpp:(.text+0x38): multiple definition of `MyClass::run()'; /tmp/ccLhxS6v.o:MyMain.cpp:(.text+0x38): first defined here
collect2: error: ld returned 1 exit status
If I have understood the concept correctly, the function headers within the class serve only as placeholders. The actual functionality is then "overwritten" by the external functions, which also contain a body.
And why does the error message say, that the function is already defined in the MyMain.cpp?
I have also seen that there are many similar questions here, but unfortunately I could not expand my understanding of the basic problem to solve it.
Is it possible that I am using the command to build the class with C++ incorrectly or that I can save the #include "MyClass.cpp"?
Kind regards
Several things wrong. here's the steps to put it right
Rename MyClass.cpp to MyClass.h.
Create a new empty file MyClass.cpp
Move the function definitions MyClass::usage() { .. } and MyClass::run() { .. } from MyClass.h to MyClass.cpp. You should probably also move #include <iostream> but this is not essential.
Add #include "MyClass.h" to MyClass.cpp
Change #include "MyClass.cpp" to #include "MyClass.h" in MyMain.cpp
Then build as you are doing now. That part is correct.
Essentially the technique is to separate your code into declarations and definitions. The declarations go into header files, which are included in the cpp files. The cpp files contain the definitions and are what you compile.
I'm wide awake at 1AM trying to figure out a compilation error I'm having.
I can't really write the exact code but I'll do my best to make my question clear.
ClassWithTemplateFunction.hpp
#include "StructA.hpp"
#include "ClassB.hpp"
class ClassWithTemplateFunction
{
template<typename A>
void MyTemplateFunc();
}
ClassWithTemplateFunction.cpp
template<typename T>
void ClassWithTemplateFunction::MyTemplateFunc()
{
// code block
}
StructA.hpp
struct ClassWithTemplateFunction;
struct StructA
{
void StructAFunc(ClassWithTemplateFunction* templ);
}
StructA.cpp
#include "ClassWithTemplateFunction.hpp"
#include "StructA.hpp"
StructA::StructAFunc(ClassWithTemplateFunction* templ)
{
templ->MyTemplateFunc<SomeTemplate>();
}
The above codes work great. "SomeTemplate" is also another class. But then I added a new class which also uses the template function:
ClassB.hpp
class ClassWithTemplateFunction;
class ClassB
{
void ClassBFunc();
}
ClassB.cpp
#include "ClassB.hpp"
#include "ClassWithTemplateFunction.hpp"
void ClassB::ClassBFunc(ClassWithTemplateFunction* templ)
{
templ->MyTemplateFunc<SomeTemplate>();
}
And for some reason, this now introduced a linker error (undefined reference to MyTemplateFunc()). I can't figure out why it suddenly produced this issue. Obviously it can be fixed by moving the definition to the header file, but I want to understand, before adding ClassB, the code works just fine.
If ClassWithTemplateFunction.cpp instantiates MyTemplateFunc with some template arguments somehow (e.g. by calling it), you'll be able to use MyTemplateFunc with the exact same arguments anywhere in the program.
That's why you don't get an undefined reference in the first case.
But it's not possible for an invocation of MyTemplateFunc with the exact same template arguments in a different file to cause an undefined reference. Please check if the template argument is really the same in both cases.
I'm comparatively new to C++ so I tested some things out in Xcode, and found a really weird thing.
This is my 'Testing.h' file
#ifndef Testing_h
#define Testing_h
class Testing{
private:
int a;
public:
Testing(int a=3);
void hey(int b);
};
#endif
This is my 'Testing.cpp' file
#include "Testing.h"
Testing::Testing(int a){
a = 4;
}
And finally, this is the 'main.cpp' file
#include <iostream>
#include "Testing.h"
using namespace std;
int main(){
Testing a;
//Apparently not completing the definitions of every abstract methods in the class is not a problem
}
I only declared 'void hey(int b)' in 'Testing.h' but have not defined it in 'Testing.cpp'. So I was wondering how it is possible for the compiler to successfully compile the 'main.cpp' without having enough information of 'void hey(int b)'. Thanks in advance!
Because you never require there to be a definition for hey().
You can require a definition by calling it, for example :
a.hey(42);
And you'll see that the linker isn't too happy because hey is an undefined reference.
Testing a;//Apparently not completing the definitions of every abstract methods in the class is not a problem
You defined constructor with default value a=3 but calling both constructor argument and class parameter the same name is bad practice.
Instead you can write this:
//Testing.h
#ifndef Testing_h
#define Testing_h
using namespace std;
class Testing{
private:
int number;
public:
Testing(int a=3): number(a = 4){}//it's the same as your implementation in cpp file
void hey(int b);
int getNumber() {return number;}
};
#endif
//main.cpp
#include <iostream>
#include "Testing.h"
int main()
{
Testing object;
cout<<object.getNumber();// returns 4
return 0;
}
And why hey compiles?
During building your project compiler translates your source code into object code by verifying the syntax. After that process linker checks the definitions marked by whole phrases. Source code is compiled from each file provided. Linker doesn't care for the implementation presence, it only looks it up if a method is used by the program. So even without implementation of hey your program compiles.
Last remark
It's discouraged to include .cpp files use headers instead. Sometimes you can get yourself into multiple definitions of the same functions causing compiler errors.
I'm trying to declare an object from a class in another file. I have added the #include "transfer.h" into my metadata.cpp file, but I'm getting the following error:
metadata.o: In function `importMetadata':
metadata.cpp:(.text+0x81): undefined reference to A::B::C::Transfer::Transfer()'
metadata.cpp:(.text+0x81): undefined reference to A::B::C::Transfer::~Transfer()'
And Transfer is defined with in transfer.h
namespace A{
namespace B{
namespace C{
class Transfer {
public:
Transfer();
~Transfer();
int copydata();
... more code goes here.
};
}
}
}
The file transfer.cpp looks like this:
Transfer::Transfer(){
}
Transfer::~Transfer(){
}
I'm also doing an using namespace A::B::C; on the header of the metadata.cpp file. Could someone please help me on that?
In the function int importMetadata() in metadata.cpp I'm declaring Transfer transfer; so in metadata.cpp I'm doing 'transfer.copydata();`
Since you have linker error and not a compiler error this tells you that your #include statement is doing what you want and the compiler recognizes the Transfer class and its constructor. The error occurs when the linker tries to find a reference to the implementation of the Transfer::Transfer() function in one of the .o or .lib files its told to link but cannot find it.
It's likely you have a transfer.cpp to go along with the transfer.h and this file is missing the implementation of the Transfer constructor and destructor. This could be because the functions are missing altogether or have been accidentally defined with a different signature.
So transfer.cpp should look something like:
A::B::C::Transfer::Transfer()
{
}
A::B::C::Transfer::~Transfer()
{
}
Another possibility is that you are trying to link the implementaiton of transfer from a library. In this case you would need to tell your linker to use the .lib file as input. The syntax for this will depend on the compiler you are using.
Hopefully you left out part of your transfer.cpp file, but in case you didnt it should define the namespace to match your header file like such:
namespace A{
namespace B{
namespace C{
Transfer::Transfer(){
}
Transfer::~Transfer(){
}
}
}
}
In case you have fully defined the namespaces, either inline or as above, you'll want to make sure you have the transfer.cpp file included in your project. Seems like the linker is unable to find your source file.
Okay, so this is really werid. I've never encountered anything like this.
Part of my program (Fails to compile) contains three namespaces as following:
// namespaceA.h
namespace A {
enum Kind { jimmy, david };
}
// end of namespaceA.h
// namespaceB.h
#include "namespaceA.h"
namespace B {
class Tree {
public:
Tree *prev;
Tree *next;
Tree *down;
A::Kind kind;
Tree();
~Tree();
};
}
// end of namespaceB.h
// Implementation details of the class are placed in namespaceB.cc
// Constructor / Desctructor defined in the namespaceB.cc file!
// Something like this,
#include "namespaceB.h"
namespace B {
inline Tree::Tree() { ... }
inline Tree::~Tree() { ... }
}
// namespaceC.cc
#include "namespace.B"
namespace C {
void run() {
B::Tree *tree; // FINE
B::Tree tree; // Fail to compile!?
}
}
// end of namespaceC.cc
Now, g++ went along just fine but the linker ld complains:
"namespaceC.cc: undefined reference to `B::Tree::Tree()'
"namespaceC.cc: undefined reference to `B::Tree::~Tree()'
I have never ever encountered anything like this before... This just seems really weird, I don't even know any words/terms to describe this problem.
I would much appreciate any help.
Thanks,
namespaceC.cc: undefined reference to `B::Tree::Tree()'
namespaceC.cc: undefined reference to `B::Tree::~Tree()'
Those are not compiler errors, they are linker errors. The problem is that you declared the constructor and destructor, but never defined them. So the compiler finds the declarations and accepts them, but the linker cannot find the definitions to link the references to.
See this answer for what is a declaration and what is a definition and what they are good/needed for.
Your definitions of B::Tree::Tree() and B::Tree::~Tree() are declared inline. This means they are only available in that source file, not any others.
Either removing inline from the definitions, or moving the inline definitions into a header file included by all source files that need them, should fix the link errors.
You have to write the constructor and destructor for B::Tree somewhere either inline or in namespaceB.cc. By creating an instance of B, you are requiring the existence of the constructor and destructor.
The pointer compiles fine because all pointers are the same. It's just the semantics allowed for different object types differ.
It would have compiled find up until the point you tried to use it.
But to create an actual object, you need the actual definition.
To use definitions from another namespace, you either used scopes, or use using:
#include "namespace.B"
using namespace B;
namespace C {
void run() {
Tree *tree; // FINE
Tree tree; // Fail to compile!?
}
}
or:
#include "namespace.B"
namespace C {
void run() {
B::Tree *tree; // FINE
B::Tree tree; // Fail to compile!?
}
}
You declare the Tree constructor & destructor, but you don't show us where you define them (you just say you implement Tree in namespaceB.cc)
Assuming you have defined them, you must ensure you are including both namespaceC.o and namespaceB.o on your link line.
That's not a namespace problem, neither a compiler error. The compiler is happy, but linker fails to find the definition of B::Tree::Tree(). You need to supply the source file for implementation, or use -c flag to "just compile".
First, you declared constructor and destructor of class Tree yourself so compiler didn't provide default implementation - you need to implement them yourself! (Or just remove those declarations...).
It is not enough to include headers but you need to explicitly say that you're using namespaces from those headers:
In namespaceC.cc add using namespace B; after you include namespace.B or, even better, prepend types with a namespace qualifier:
B::Tree *tree;
B::Tree tree;
I tried the codes in Visual studio 2005. If I remove the "inline" in namespaceB.cc for the constructor and destructor, it can link without errors.
Then I found this post: G++ won't accept inline constructors in C++
it says that for inline functions you must have its definition in every file that calls the function. So it is recommended to put inline definition in header file.