Why could I not find the class in preprocessor? - c++

This might be very naive, but I am quite confused about the preprocessor of cpp:
I defined a header file-- Node.h:
#ifndef NODE_H_
#define NODE_H_
#include<iostream>
class Node{
friend std::ostream &operator<<(std::ostream &os, const Node & n);
public:
Node(const int i = -1);
private:
Node * next;
int value;
friend class List;
};
#endif
Then I defined the methods in Node.cpp:
#include "Node.h"
using namespace std;
Node::Node(const int i):value(i), next(NULL){}
ostream& operator <<(ostream & os, const Node& n){
return os<<"value : "<<n.value<<endl;
}
lastly, I have a test.cpp file to check the preprocessor:
#include "Node.h"
//#include <iostream>
using namespace std;
int main(){
Node * n = new Node;
cout<<*n;
}
however, when I tried to compile with gcc, I got the following error:
/home/xuan/lib/singleLinkedList/test.cpp:6:‘Node::Node(int)’undefined reference

Given your files, when I run:
$ g++ test.cpp
/tmp/ccM7wRNZ.o:test.cpp:(.text+0x2c): undefined reference to `Node::Node(int)'
/tmp/ccM7wRNZ.o:test.cpp:(.text+0x44): undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Node const&)'
/usr/lib/gcc/i686-pc-cygwin/4.5.3/../../../../i686-pc-cygwin/bin/ld: /tmp/ccM7wRNZ.o: bad reloc address 0x0 in section `.ctors'
collect2: ld returned 1 exit status
... but if I run:
Simon#R12043 ~/dev/test/cpp
$ g++ test.cpp node.cpp
Simon#R12043 ~/dev/test/cpp
$
Thus, I think you are not including node.cpp among the files to be linked into the project. That is, it is the linker that is not finding the Node class.

Related

Undefined reference to a function in a class defined in anther file while using typename

I have been stuck for a while now and am unable to figure out why I am getting this compile error.
Node.hpp
#ifndef H1
#define H1
template <typename T>
class Node{
private:
T data;
public:
T getData();
};
#endif
Node.cpp
#include "Node.hpp"
template<typename T>
T Node<T>::getData(){
return data;
}
main.cpp
#include <bits/stdc++.h>
#include "Node.hpp"
using namespace std;
int main()
{
Node<int> *n = new Node<int>();
cout << n->getData();
}
g++ main.cpp Node.cpp -std=c++17
O/P: main.cpp:(.text+0x24): undefined reference to `Node::getData()'collect2: error: ld returned 1 exit status
PS: I tried the same thing without any template (use a primitive datatype instead), I do not get any error. So this probably has got something to do with the typename. Would be great if someone could tell me what is wrong here.
Node.hpp
#ifndef H1
#define H1
template <typename T>
class Node{
private:
T data;
public:
T getData() { return data; }
};
//or define it here
#endif
Then no need for Node.cpp. You might want to consider returning a const reference if your use-case allows it as T now requires a copy constructor. Although maybe that's what you want, I don't know your use-case.
See Why can template only be defined in header files

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();
//...
}
}

invalid use / forward declaration of 'struct Node'

For a school project I am trying to make a binary search tree at the same time we are supposed to learn how to use 'friendship' in classes. The errors I get while compiling are: [I put comments in code where the errors originate from for clarity]
$ make -f makefile.txt
g++ -Wall -W -Werror -pedantic -g -c BST.cpp
BST.cpp: In member function `void BST::insert(std::string, std::string)':
BST.cpp:13: error: invalid use of undefined type `struct Node'
BST.h:19: error: forward declaration of `struct Node'
makefile.txt:9: recipe for target `BST.o' failed
make: *** [BST.o] Error 1
Basically I want to be able to access the Node class as if the class was nested (I am not allowed to nest it for the sake of this programming assignment however). Obviously simply using 'ptr->m_data' would not work, but what could I do to make it work?
Node.h
#ifndef NODE_H_INCLUDED
#define NODE_H_INCLUDED
#include <iostream>
#include <string>
using namespace std;
class BST;
class Node
{
public:
Node(string key, string data)
{n_key = key; n_data = data;}
~Node();
private:
string m_key;
string m_data;
Node *m_left;
Node *m_right;
//Node *m_parent;
};
#endif // NODE_H_INCLUDED
BST.h
#ifndef BST_H_INCLUDED
#define BST_H_INCLUDED
#include <iostream>
#include <string>
using namespace std;
class BST
{
public:
BST()
{m_root = NULL;}
~BST();
void insert(string key, string data);
void find(string key);
void remove(string key, string data);
void print();
friend class Node; //Error: forward declaration of 'struct Node'
private:
Node* m_root;
};
#endif // BST_H_INCLUDED
Why is it that when I call the below line of code it reads out the above error messages? (Note: the below code is from BST.cpp)
#include "BST.h"
void BST::insert(string key, string data)
{
Node* yPtr = NULL;
Node* xPtr = m_root;
while(xPtr != NULL)
{
yPtr = xPtr;
if(key < xPtr->m_key) //Error: invalid use of undefined type 'struct Node'
{
}
}
}
The compiler has not seen the definition of Node when it gets to that line in BST.cpp. Note that that is the first line where the compiler needs to see the structure of Node. You need to #include "Node.h" in BST.cpp.

C++ undefined reference to a linked function

I have a problem with the linking of a C++ project and I can't figure out what's wrong.
The jest of the code.
clitest.cpp
#include <iostream>
#include "node.h"
using namespace std;
int main(int argc, char** argv)
{
node<int> *ndNew = new node<int>(7);
return 0;
}
node.h
#ifndef NODE_H
#define NODE_H
#include <vector>
template <typename T>
class node
{
private:
node<T>* ndFather;
std::vector<node<T>* > vecSons;
public:
T* Data;
node(const T &Data);
};
#endif
node.cpp
#include "node.h"
using namespace std;
template <typename T>
node<T>::node(const T &Data)
{
this->Data = &Data;
this->ndFather = 0;
this->vecSons = (new vector<T>());
};
The compiler command that was used is
g++ -Wall -g clitest.cpp node.cpp -o clitest
The error log is goes like this
clitest.cpp: In function ‘int main(int, char**)’:
clitest.cpp:8:16: warning: unused variable ‘ndNew’ [-Wunused-variable]
node<int> *ndNew = new node<int>(7);
^
/tmp/cc258ryG.o: In function `main':
clitest.cpp:8: undefined reference to `node<int>::node(int const&)'
collect2: error: ld returned 1 exit status
make: *** [blist] Error 1
I have spent a decent amount of time shifting the code around, Trying to identify the problem and I either miss something basic, Or it's something I don't know about C++ linkage.
When using templates, the compiler needs to know how to generate the code for the class when it is instantiated. The undefined reference error is caused because the compiler did not generate the node<int>::node(int const &) constructor. See, e.g. Why can templates only be implemented in the header file?
You have a couple of options:
Put the implementation in node.h (node.cpp is removed as it not needed)
Put the implementation in a file that is #included at the bottom of node.h (usually the file would be called node.tpp)
I suggest putting the implementation in node.h and removing node.cpp. Note that the code in your example is not valid c++: the member variable vecSons is not a pointer so the line vecSons = new vector<T>() will give a compiler error. The following code could be a starting point for the full implementation:
#ifndef NODE_H
#define NODE_H
#include <vector>
template <typename T>
class node
{
private:
node<T>* ndFather;
std::vector<node<T>* > vecSons;
public:
const T* Data;
node(const T &d) :
ndFather(0),
vecSons(),
Data(&d)
{
}
};
#endif
Use -I. before the .cpp files, so that the compiler knows to look for .h files.
g++ -Wall -I. clitest.cpp node.cpp -o clitest
Or just -I:
g++ -Wall -I clitest.cpp node.cpp -o clitest

C++ failed linkage, undefined reference [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can templates only be implemented in the header file?
Undefined reference to function template when used with string (GCC)
C++ templates, undefined reference
I feel I'm missing something linking a C++ project.
I'm not sure if the problem is in the header sources or includes so I made a minimal code sample to demonstrate it.
Main module
minmain.cpp:
#include <stdio.h>
#include <vector>
#include <string>
#include "nodemin.h"
using namespace std;
int main()
{
// Blist libs are included
Node<int>* ndNew = ndNew->Root(2);
return 0;
}
Header file
nodemin.h:
#ifndef NODETEMP_H_
#define NODETEMP_H_
using namespace std;
template<class T>
class Node
{
protected:
Node* m_ndFather;
vector<Node*> m_vecSons;
T m_Content;
Node(Node* ndFather, T Content);
public:
// Creates a node to serve as a root
static Node<T>* Root(T RootTitle);
};
#endif
node module
nodemin.cpp:
#include <iostream>
#include <string.h>
#include <vector>
#include "nodemin.h"
using namespace std;
template <class T>
Node<T>::Node(Node* ndFather, T Content)
{
this->m_ndFather = ndFather;
this->m_Content = Content;
}
template <class T>
Node<T>* Node<T>::Root(T RootTitle) { return(new Node(0, RootTitle)); }
Compile line:
#g++ -Wall -g mainmin.cpp nodemin.cpp
Output:
/tmp/ccMI0eNd.o: In function `main':
/home/******/projects/.../src/Node/mainmin.cpp:11: undefined reference to`Node<int>::Root(int)'
collect2: error: ld returned 1 exit status
I tried compiling into objects but the linking still failed.
Add template class Node<int>; to nodemin.cpp:
#include <iostream>
#include <string.h>
#include <vector>
#include "nodemin.h"
using namespace std;
template <class T>
Node<T>::Node(Node* ndFather, T Content)
{
this->m_ndFather = ndFather;
this->m_Content = Content;
}
template <class T>
Node<T>* Node<T>::Root(T RootTitle) { return(new Node(0, RootTitle)); }
template class Node<int>;