Linker can't find function definition in a namespace - c++

I get this /tmp/ccnL7Yz1.o: In function 'main':
main.cpp:(.text+0x70): undefined reference to 'dng::genDungeon()'
main.cpp:(.text+0xf0): undefined reference to 'dng::clrDungeon(char**)'
collect2: error: ld returned 1 exit status error when I'm trying to compile my program. It worked great before I added namespace functions. I'm compiling it like this: g++ -std=c++11 main.cpp Dungeon.cpp
Dungeon.h
namespace dng {
char** genDungeon();
void clrDungeon(char**);
class Dungeon {
//Methods and variables
}
}
Dungeon.cpp
#include "Dungeon.h"
using namespace dng;
char** genDungeon()
{
//Stuff
}
void clrDungeon(char** dungeon)
{
//Another Stuff
}
/*Implementation of class methods
void Dungeon::genStart(){} -> like this */
main.cpp
#include "Dungeon.h"
int main ()
{
//Stuff
auto dungeon = dng::genDungeon();
//Stuff
dng::clrDungeon(dungeon);
return 0;
}
I also tried to make .o files by myself g++ -std=c++11 -c main.cpp g++ -std=c++11 -c Dungeon.cpp and then link them, but got the same error. What can be the problem?

Enclose the function definitions in the namespace dng where they are declared.
#include "Dungeon.h"
namespace dng
{
char** genDungeon()
{
//Stuff
}
void clrDungeon(char** dungeon)
{
//Another Stuff
}
//...
}
Or use qualified names.
include "Dungeon.h"
using namespace dng;
//...
char** dng::genDungeon()
{
//Stuff
}
void dng::clrDungeon(char** dungeon)
{
//Another Stuff
}
Otherwise, the functions are defined in the global namespace, and as a result, you declared four functions: two in the namespace dng and another two in the global namespace.

Related

Simple multifile c++11 compilation g++ when defining personal namespace in classes

Working with a Fedora g++, I've noticed something anoying for me.
I think I misundertands g++ behaviors with namesapce and header files.
You will see 2 versions of a very simple Class and a main function.
First one is fully embeded in single file named "mainfull.cpp" and compiles silently.
Second one is the same code distributed in three files "MaClass.hpp", "MaClass.cpp" and "main.cpp". The issue come from this version.
$ g++ -o doit MaClass.cpp main.cpp
/usr/bin/ld : /tmp/cc9IOJE8.o : in function « main » :
main.cpp:(.text+0x10) : undefined reference to « test::example::MaClass::doit() »
collect2: error: ld returned exit status 1
But the error vanishes with namespace suppression or when changing the include from the header file to the implementation file.
Here are my questions :
What is the good way to include multifiles classes with namespaces ?
How should one uses g++ in that case ?
But I am a chatterbox ; here is the code :
mainfull.cpp : no pb when compiling with : g++ -o mainfull mainfull.cpp
#include <iostream>
namespace test {
namespace example {
class MaClass {
public:
void doit();
};
}
}
int main() {
test::example::MaClass c;
c.doit();
return 0;
}
namespace test {
namespace example {
void MaClass::doit() {
::std::cout << "I did it !" << ::std::endl;
}
}
}
And here the version on witch I get doubts: (the whole remaining files)
MaClass.hpp
#ifndef MACLASS
#define MACLASS
#include <iostream>
namespace test {
namespace example {
class MaClass {
public:
void doit();
};
}
}
#endif
MaClass.cpp
#include "MaClass.hpp"
namespace test {
namespace example {
void MaClass::doit() {
::std::cout << "I did it !" << ::std::endl;
}
}
}
main.cpp
#include "MaClass.hpp"
int main() {
test::example::MaClass c;
c.doit();
return 0;
}
The issue occurs with :
g++ -o doit MaClass.cpp main.cpp -std=c++11
I don't know the reason of that. I know that the problem come from me and not from Fedora.
Any help would be apreciated.
I have no problem on Visual Studio 2019 neither with the one nor the other version ; everything is automatic, I should have miss something.

template class and free function namespace problems with implementation

I have a class defined like this (trivial includes and preprocessor wrappers, etc. are omitted, but they are there):
In Matrix.h
namespace matrixmanip {
template<typename T>
class Matrix {
public:
void someFunc() const;
//...
};
template<typename T>
void Matrix<T>::someFunc() const {
//...
}
} // namespace matrixmanip
In bitTransform.h
#include "Matrix.h"
namespace matrixmanip {
Matrix<char> bitExpand(const Matrix<char> &mat);
} // namespace matrixmanip
In bitTransform.cpp
#include "bitTransform.h"
using namespace matrixmanip;
Matrix<char> bitExpand(const Matrix<char> &mat) {
mat.someFunc();
//...
}
In tester.cpp
#include "Matrix.h"
#include "bitTransform.h"
matrixmanip::Matrix<char> A ... // construct a character matrix, details of which are unimportant here
matrixmanip::Matrix<char> B = matrixmanip::bitExpand(A);
However, when I compile and link like this:
g++ -c tester.cpp
g++ -c bitTransform.cpp
g++ -Wall -O2 tester.o bitTransform.o -o tester
I get an undefined reference error, specifically
/tmp/ccateMEK.o: In function `main':
tester.cpp:(.text+0xbf9): undefined reference to `matrixmanip::bitExpand(matrixmanip::Matrix<char> const&)'
collect2: error: ld returned 1 exit status
Why am I getting this error? It seems to me that my namespace resolution is okay and my linkage is fine...
bitExpand defines a free function in global namespace, not in matrixmanip namespace. using directive does not move definitions into the namespace being used. You should put definition in proper namespace directly:
namespace matrixmanip
{
Matrix<char> bitExpand(const Matrix<char> &mat)
{
mat.someFunc();
//...
}
}

Ttrying to understand Classes and headers

**PROBLEM SOLVED. It appears that i had created an extra header by mistake, and since i deleted him , it worked. **
So i am trying to understand about classes and headers and how i can make them work together.
I am following an online tutorial but it seems that something is going wrong in my code.
The problem is that when i try to run the main it gives me this error:
multiple definition of Cat::speak() and all the other functions.
main.cpp
#include <iostream>
#include "class.h"
using namespace std;
int main()
{
Cat jim;
jim.makehappy();
jim.speak();
Cat george;
george.makesad();
george.speak();
return 0;
}
class.cpp
#include <iostream>
#include "class.h"
using namespace std;
void Cat::speak()
{
if (happy)
{
cout << "meoww" << endl;
}
else
{
cout << "sssss" << endl;
}
}
void Cat::makehappy()
{
happy = true;
}
void Cat::makesad()
{
happy = false;
}
class.h
#ifndef CLASS_H_INCLUDED
#define CLASS_H_INCLUDED
class Cat
{
private:
bool happy;
public:
void makehappy();
void makesad();
void speak();
};
#endif // CLASS_H_INCLUDED
From what you have shown here there should be no problems. What you could do to temporarily resolve this to find out if you are actually defining this function in several places is to wrap your class in a namespace.
class.h
#ifndef CLASS_H_INCLUDED
#define CLASS_H_INCLUDED
namespace myNamespace {
class Cat {
private:
bool happy;
public:
void makehappy();
void makesad();
void speak();
};
} // namespace myNamespace
#endif // CLASS_H_INCLUDED
class.pp
#include <iostream>
#include "class.h"
// using namespace std; // Don't Use - This is Bad Practice
// Can cause name clashing when trying to resolve name lookup
namespace myNamespace {
void Cat::speak() {
if (happy) {
std::cout << "meoww" << std::endl;
} else {
std::cout << "sssss" << std::endl;
}
}
void Cat::makehappy() {
happy = true;
}
void Cat::makesad() {
happy = false;
}
} // namespace myNamespace
main.cpp
#include <iostream>
#include "class.h"
// using namespace std; // Again -Bad Practice
int main() {
using namespace myNamespace;
Cat jim;
jim.makehappy();
jim.speak();
Cat george;
george.makesad();
george.speak();
return 0;
}
Try this to see if you are getting the same compiler error. This should help you to see if you are defining this function in multiple spaces. Also by removing the using namespace std; and just using the scope resolution operator to the std:: namespace will help to eliminate any possible problems and any possible future problems.
How are you compiling the code? You need to make sure that you are building the specific "class.o" and "main.o" files separately before linking them together. Here is an example Makefile.
all: main
main: main.o class.o
g++ main.o class.o -o main
main.o: main.cpp class.h
g++ -c main.cpp
class.o: class.cpp class.h
g++ -c class.cpp
It looks like you are using double inclusion guards so I don't think that is the problem. Check out this answer for a more in-depth explanation of what is happening: Error with multiple definitions of function

c++ 'undefined reference to' error

I'm having one of those "undefined reference to " errors when compiling a c++ program. I know this is common pitfall, but so far was unable to figure out what I'm doing wrong.
Here's the relevant code. Ex1Two_Sum.h:
#ifndef EX1TWO_SUM_H
#define EX1TWO_SUM_H
#include <vector>
using namespace std;
namespace ddc {
class Ex1Two_Sum
{
public:
void f();
protected:
private:
};
}
#endif
Ex1Two_Sum.cpp:
#include <vector>
#include <cstddef>
#include <iostream>
using namespace std;
namespace ddc {
class Ex1Two_Sum {
public:
void f(){
cout << "works" << endl;
}
};
}
And finally, main.cpp:
#include <iostream>
#include "Ex1Two_Sum.h"
using namespace std;
using namespace ddc;
int main()
{
Ex1Two_Sum ex1;
ex1.f();
return 0;
}
I compile as follows:
g++ -std=c++11 -c Ex1Two_Sum.cpp
g++ -std=c++11 -c main.cpp
g++ Ex1Two_Sum.o main.o
yielding the following message:
main.o: In function `main':
main.cpp:(.text+0x2c): undefined reference to `ddc::Ex1Two_Sum::f()'
collect2: error: ld returned 1 exit status
Your source file redefines the whole class, with an inline function definition, when it just needs to provide a non-inline function definition.
#include "Ex1Two_Sum.h"
void ddc::Ex1Two_Sum::f() {
std::cout << "should work\n";
}
Also, please don't put using namespace std; in a header. Not everyone wants the global namespace polluted in potentially surprising ways.
First, which line of the command throws that error?
Second, I think you forgot to include the Ex1Two_Sum.h in the Ex1Two_Sum.cpp
Third you need to change class ....... in Ex1Two_Sum.cpp to:
void Ex1Two_Sum::f(){...}

Simple class usage+undefined reference

I have just created this simple class.When I compile, I am getting the following error.
caller.o: In function main':
caller.cpp:(.text+0x15): undefined reference toReader::Reader(int)'
collect2: ld returned 1 exit status
Reader.h
#ifndef READER_H
#define READER_H
class Reader
{
private:
int m_month;
Reader() {}
public:
Reader(int month);
void SetDate(int month);
int GetMonth() {return m_month;}
};
#endif
Reader.cpp
#include "Reader.h"
Reader::Reader(int month);
{
SetDate(month);
}
void Reader::SetDate(int month)
{
m_month=month;
}
main program
#include <iostream>
using namespace std;
#include "Reader.h"
int main()
{ int i;
i=5;
Reader rd(i);
i=rd.GetMonth();
cout<<i;
return 0;
}
There is a ; semicolon that should not be there.
Reader::Reader(int month)//; remove semicolon from this line !!!
{
SetDate(month);
}
You need to compile all your source files into object files, and then link the object files together to produce the program.
This can be done in one step:
gcc Reader.cpp main.cpp
Or in two separate steps:
gcc -c Reader.cpp main.cpp
gcc Reader.o main.o
Of course, you should normally have an IDE, Makefile or buildsystem generator (such as CMake) take care of this for you.