Why does my class not link? - c++

This week I started to upgrade my knowledge from C to C++, I would like to overload some operators
I have a class called Matrix
#include "lcomatrix.h"
inline Matrix::Matrix(unsigned rows, unsigned cols) :
rows_(rows), cols_(cols)
{
data_ = new double[rows * cols];
}
inline Matrix::~Matrix() {
delete[] data_;
}
inline double& Matrix::operator()(unsigned row, unsigned col) {
return data_[cols_ * row + col];
}
inline double Matrix::operator()(unsigned row, unsigned col) const {
return data_[cols_ * row + col];
}
The content of lcomatrix.h is
#include <iostream>
class Matrix {
public:
Matrix(unsigned rows, unsigned cols);
double& operator()(unsigned row, unsigned col);
double operator()(unsigned row, unsigned col) const;
~Matrix(); // Destructor
Matrix& operator=(Matrix const& m); // Assignment operator
private:
unsigned rows_, cols_;
double* data_;
};
Main.cpp
#include "lcomatrix.h"
#include <iostream>
/*-
* Application entry point.
*/
int main(void) {
Matrix mx(12,12);
//std::cout << mx << std::endl;
return 0;
}
Make file:
CPPFLAGS=-I /path/lcomatrix/
EFLAGS=
all : main.o lcomatrix.o
g++ $(EFLAGS) -o main.out main.o lcomatrix.o
main.o: lcomatrix.o
g++ $(EFLAGS) $(CPPFLAGS) -c main.cpp
lcomatrix.o:
g++ $(EFLAGS) -c /home/robu/UbuntuOne/ChibiOS-RPi/lcomatrix/lcomatrix.cpp
clean:
rm *.o main.out
When I try to build I receive the following link error:
make all
g++ -c /home/robu/UbuntuOne/ChibiOS-RPi/lcomatrix/lcomatrix.cpp
g++ -I /home/robu/UbuntuOne/ChibiOS-RPi/lcomatrix/ -c main.cpp
g++ -o main.out main.o lcomatrix.o
main.o: In function `main':
main.cpp:(.text+0x1b): undefined reference to `Matrix::Matrix(unsigned int, unsigned int)'
main.cpp:(.text+0x2c): undefined reference to `Matrix::~Matrix()'
collect2: error: ld returned 1 exit status
make: *** [all] Error 1
I guess this a really stupid error, but as a beginner I couldn't figure out the solution.

Your method definitions are all inline. In order to inline a function, the compiler needs to see its definition whenever it is compiling the code that uses it.
Either put the function definitions somewhere they can be seen at the point of use - in the header, or in another file #included by Main.cpp - or don't mark them as inline.

Related

g++/make failing while linking object files

So, I am trying to learn c++ and a little bit about makefiles. However, for some reason I cannot get my files to link properly. The makefile is the following:
OBJS = stl_test.o src/t_stack.o src/matrix_w.o src/matrix.o
stl_test: $(OBJS)
g++ -o stl_test $(OBJS) -lm
.cpp.o:
g++ -c -O -I. $< -o $# -std=c++0x
stl_test.o: include/t_stack.h
src/matrix.o: include/matrix.h
src/matrix_w.o: include/matrix_w.h
src/t_stack.o: include/t_stack.h
include/matrix_w.h: include/matrix.h
touch include/matrix_w.h
include/t_stack.h: include/matrix_w.h include/matrix.h
touch include/t_stack.h
The problem that i am currently having is the following:
touch include/matrix_w.h
touch include/t_stack.h
g++ -c -O -I. stl_test.cpp -o stl_test.o -std=c++0x
g++ -c -O -I. src/t_stack.cpp -o src/t_stack.o -std=c++0x
g++ -c -O -I. src/matrix_w.cpp -o src/matrix_w.o -std=c++0x
g++ -c -O -I. src/matrix.cpp -o src/matrix.o -std=c++0x
g++ -o stl_test stl_test.o src/t_stack.o src/matrix_w.o src/matrix.o -lm
src/t_stack.o: In function `T_stack::pop()':
t_stack.cpp:(.text+0xc9): undefined reference to `Matrix<double>::display() const'
t_stack.cpp:(.text+0xd7): undefined reference to `Matrix<double>::~Matrix()'
src/t_stack.o: In function `T_stack::push_translation(double, double, double)':
t_stack.cpp:(.text+0x1af): undefined reference to `Matrix<double>::Matrix(int, int, double*)'
t_stack.cpp:(.text+0x239): undefined reference to `Matrix<double>::multiply(Matrix<double>*) const'
src/t_stack.o: In function `T_stack::push_scaling(double, double, double)':
t_stack.cpp:(.text+0x33f): undefined reference to `Matrix<double>::Matrix(int, int, double*)'
t_stack.cpp:(.text+0x3c9): undefined reference to `Matrix<double>::multiply(Matrix<double>*) const'
src/t_stack.o: In function `T_stack::T_stack()':
t_stack.cpp:(.text+0x4f4): undefined reference to `Matrix<double>::Matrix(int, int, double*)'
t_stack.cpp:(.text+0x516): undefined reference to `Matrix<double>::copy() const'
src/t_stack.o: In function `T_stack::~T_stack()':
t_stack.cpp:(.text+0x64c): undefined reference to `Matrix<double>::display() const'
t_stack.cpp:(.text+0x65a): undefined reference to `Matrix<double>::~Matrix()'
t_stack.cpp:(.text+0x74f): undefined reference to `Matrix<double>::display() const'
collect2: ld returned 1 exit status
make: *** [stl_test] Error 1
I am not entirely sure what the problem is. I tried changing the order of the files in the g++ command but that didnt work either. I have tried checking the headers of the files and I think they are correct but I have posted fragments here anyways:
stltest.cpp
#include <iostream>
#include "include/t_stack.h"
using namespace std;
int main(void) {
......
matrix.h
#ifndef _MATRIX_
#define _MATRIX_
#include <iostream>
using namespace std;
......
matrix_w.h
#ifndef _MATRIX_W_
#define _MATRIX_W_
#include "include/matrix.h"
class Matrix_w {
......
t_stack.h
#ifndef _T_STACK_H_
#define _T_STACK_H_
#include <list>
#include <stack>
#include <iostream>
#include "include/matrix.h"
#include "include/matrix_w.h"
using namespace std;
class T_stack {
private:
// matrix stack
stack<Matrix_w*, list<Matrix_w* > >* m_stack;
// inverse transform list
list<Matrix<double>* >* t_list;
public:
T_stack();
void pop();
void push_translation(double tx, double ty, double tz);
void push_scaling(double sx, double sy, double sz);
int size() const;
~T_stack();
};
#endif
Any ideas what the problem might be? Thanks!
Just in case, here is the implementation of the methods that it complains about (the file is called matrix.cpp)..
#include "include/matrix.h"
using namespace std;
template <typename T>
Matrix<T>::~Matrix() {
delete data;
}
template <typename T>
Matrix<T>::Matrix(int width, int height) {
this->height = height;
this->width = width;
this->data = new T[height*width];
}
template <typename T>
Matrix<T>::Matrix(int width, int height, T* data) {
this->height = height;
this->width = width;
this->data = new T[height*width];
int i;
//may be able to speed this up by using memcpy
// Not sure whether this is a good idea anyways
for(i=0; i < height*width; i++) {
this->data[i] = data[i];
}
}
template <typename T>
T Matrix<T>::at(int x, int y) const {
#ifdef __DEBUG
if(x < width && y < height) {
return data[y*width + x];
} else {
throw 1;
}
#else
return data[y*width + x];
#endif
}
template <typename T>
void Matrix<T>::set(int x, int y, T val) {
#ifdef __DEBUG
if(x < width && y < height) {
data[y*width + x] = val;
} else {
throw 1;
}
#else
data[y*width + x] = val;
#endif
}
//this function is just for convenience but it should only work
//when T is some number type ----ASK!!
template <typename T>
void Matrix<T>::display() const {
int i, j;
cout << "[" << endl;
for(i=0; i<height; i++) {
for(j=0; j<width; j++) {
cout << " " << data[i*width + j];
}
cout << endl;
}
cout << "]" << endl;
}
template <typename T>
Matrix<T>* Matrix<T>::multiply(Matrix<T>* other) const {
#ifdef __DEBUG
if(other->height != width) {
throw 1;
}
#endif
T* res = new T[other->width*height];
int i,j,k;
T sum;
for(i=0; i<height; i++) {
for(j=0; j<other->width; j++) {
sum = 0;
for(k=0; k<width; k++) {
sum += other->data[k*other->width+j]*data[i*width+k];
}
res[i*other->width + j] = sum;
}
}
return new Matrix<double>(other->width, height, res);
}
template <typename T>
Matrix<T>* Matrix<T>::copy() const {
return new Matrix<T>(width, height, data);
}
When you have a template class or functions, the functions should be inline, and the body should be in the header file, in the class or outside with inline keyword in the class.
The difference is that, unlike regular class, the compiler is compiling the class for each type you are using as the template type.
If you are not using it at all, the file won't be compiled even once.
In several compilers your code will work even if it split to h and cpp. but you can't count on it.
I see, it would be typical to implement your template as inline functions. You can, however, use an explicit instantiation of the template in your matrix.cpp file. At the bottom, after the definitions, you could try to add:
template class Matrix<double>;
If you're not using precompiled headers, this actually might make a lot of sense. Also, it can go pretty much anywhere I think, but you can only have one of those statements per program, if you instantiate a Matrix in two places it may or may not work.

C++: Undefined reference to function in namespace

Here I am, trying to figure out what's wrong with my code without success :(
I'm writing a resampler but I guess that's of no interest at all, I'm just trying yo make this stupid warning go away. Anyway, here's my code:
ddc.hpp
#ifndef __DIGITAL_DOWN_CONVERTER_H__
#define __DIGITAL_DOWN_CONVERTER_H__
#include <vector>
#include "interpolator.h"
namespace ddc {
void decimate(std::vector<float> &, unsigned int);
void expand(std::vector<float> &, unsigned int);
void perform_resampling(std::vector<float>, unsigned int, unsigned int);
void generate_filter(std::vector<float> &, unsigned int, unsigned int);
float Sinc(float);
unsigned int mcd(unsigned int, unsigned int);
}
#endif
ddc.cpp
#include "ddc.hpp"
namespace ddc {
void perform_resampling(std::vector<float> &data, unsigned int freq_1, unsigned int freq_2) {
unsigned int i, gcd = mcd(freq_1, freq_2);
unsigned int downFactor, upFactor;
std::vector<float> filter;
downFactor = freq_1/gcd;
upFactor = freq_2/gcd;
generate_filter(filter, 1024 /* lobi della semi-sinc */, upFactor);
decimate(data, downFactor);
expand(data, upFactor);
interpolate_fft(data, filter);
}
}
main.cpp
#include <vector>
#include "ddc.hpp"
using namespace std;
int main() {
vector<float> data;
// bla bla
ddc::perform_resampling(data, 1000000, 60000);
return 0;
}
Compiling with g++ (linux) I get the following error:
$ make all
g++ -c ddc.cpp -o ddc.o -Wall -O3 -lm -m64
g++ -c main.cpp -o main.o -Wall -O3 -lm -m64
g++ ddc.o main.o -o ../bin/resampler
main.o: In function `main':
main.cpp:(.text.startup+0x255): undefine d reference to
`ddc::perform_resampling(std::vector<float, std::allocator<float> >, unsigned int, unsigned int)'
collect2: ld returned 1 exit status
make: *** [../bin/resampler] Error 1
I'm going out of my mind, please help me! What am I doing wrong? Besides, If I remove ddc:: from the main function, gcc suggests me this:
main.cpp:59:49: note: suggested alternative:
ddc.hpp:24:7: note: ‘ddc::perform_resampling’
You declare a function taking a vector by value as its first argument, then define it taking the vector by reference. This produces a separate overload, and the declared function has no definition. Presumably it should be a reference, so add & to the declaration in the header.
You would get a more useful compiler error if you defined functions outside their namespace:
void ddc::perform_resampling(std::vector<float> &data, unsigned int freq_1, unsigned int freq_2) {
// ^^^^^
// blah blah
}
since it's an error to define a function with a qualified name if it hasn't been declared.
These two are different:
void perform_resampling(std::vector<float> &data, unsigned int freq_1, unsigned int freq_2)
void perform_resampling(std::vector<float> data, unsigned int freq_1, unsigned int freq_2)
P.S. This shows one good reason to put parameter names in your prototypes, even though they aren't strictly required. With parameter names, you can compare a prototype directly to a definition, and they should match character for character
In your prototype, you are missing &
void perform_resampling(std::vector<float>, unsigned int, unsigned int);
It appears in the definition
void perform_resampling(std::vector<float> &data, unsigned int freq_1, unsigned int freq_2) {
unsigned int i, gcd = mcd(freq_1, freq_2);
unsigned int downFactor, upFactor;
std::vector<float> filter;
downFactor = freq_1/gcd;
upFactor = freq_2/gcd;
generate_filter(filter, 1024 /* lobi della semi-sinc */, upFactor);
decimate(data, downFactor);
expand(data, upFactor);
interpolate_fft(data, filter);
}

c++ undefined symbol when compiling

FIXED: had the method twice in the header file
I get the following error when trying to compile my project
% make
g++ -o p4 testTree.o tree.o node.o check.o
Undefined first referenced
symbol in file
Tree::inTree(int) tree.o
ld: fatal: Symbol referencing errors. No output written to p4
collect2: ld returned 1 exit status
*** Error code 1
make: Fatal error: Command failed for target `p4'
Makefile
p4: testTree.o tree.o node.o check.o
g++ -o p4 testTree.o tree.o node.o check.o
testTree.o: testTree.cc tree.h node.h check.h
g++ -c -Wall -Werror testTree.cc
tree.o: tree.h tree.cc node.h check.h
g++ -c -Wall -Werror tree.cc
node.o: node.h node.cc check.h
g++ -c -Wall -Werror node.cc
check.o: check.h check.cc
g++ -c -Wall -Werror check.cc
clean:
rm -f *~ *.o p4
Relevant code from tree.cc and tree.h:
tree.cc
...
bool Tree::inTree(int k) const
{
return locate(k,root) != NULL;
}
...
tree.h
#ifndef TREE_H
#define TREE_H
#include "node.h"
#include "check.h"
using namespace std;
class Tree
{
private:
Node *root;
public:
Tree();
Tree(const Tree & t);
const Tree & operator=(const Tree &t);
friend ostream & operator<<(ostream &out, const Tree &t);
bool inTree(int k) const;
double & operator[](int k);
double & operator[](int k) const;
~Tree();
bool inTree(int index);
private:
Node * locate(int k, Node *rt) const;
ostream & display(ostream &out, Node *r, int dir=Node::L) const;
void add(int k, Node*&r);
void kill(Node *&rt);
void copy(Node *rt, Node *&newRt);
};
#endif
I get the feeling that it's something really simple, but I can't seem to figure it out.
The message you are getting actually comes from the linker, not from the compiler.
One of your member functions, bool Tree::inTree(int index);, is correctly declared and defined as a const member function:
// Declaration in tree.h
bool inTree(int index) const;
// Definition in tree.cc
bool Tree::inTree(int k) const
// ^^^^^
However, in tree.h you also define this non-const overload of inTree():
// Declaration in tree.h, definition (supposedly) nowhere
bool Tree::inTree(int k)
For which no definition is provided. This is what the linker complains about.
Here is your error:
bool Tree::inTree(int k) const
{
return locate(k,root) != NULL;
}
in your .h you define
bool inTree(int);
This is a difference!

undefined reference to

This is the error I am keep getting . undefined reference to my class. I am not sure. I think I m linking them. this is how my main looks like.
#include <iostream>
#include "randomNumberMagnifier.h"
using namespace std;
int main()
{
randomNumberMagnifier r1, r2;
cout << "Random Number "<< r1.getRandomNumber();
cout << endl;
}
I am not sure what I am doing wrong.
this is what it looks like. when I compile
[singha1#cs1 p4]$ g++ -c randomNumberMagnifier.cpp
[singha1#cs1 p4]$ g++ -o p4Driver.cpp
g++: no input files
p4Driver.cpp:(.text+0x8c): undefined reference to `randomNumberMagnifier::getRandomNumber
collect2: ld returned 1 exit status
#ifndef RANDOMNUMBERMAGNIFIER_H
#define RANDOMNUMBERMAGNIFIER_H
class randomNumberMagnifier
{
int addFactor;
int multFactor;
bool addOn;
bool multOn;
int randomNumber;
static const int MAX_ADD_FACTOR = 100;
static const int MAX_MULT_FACTOR = 20;
static const int MAX_RANDOM = 200;
public:
randomNumberMagnifier();
//~randomNumberMagnifer();
randomNumberMagnifier& operator=(const randomNumberMagnifier& rhs);
randomNumberMagnifier(const randomNumberMagnifier& arandom);
randomNumberMagnifier(bool aState, bool mState);
int randomMagnifier();
int getAdd();
int getMult();
bool getAddState();
bool getMultState();
int getRandomNumber();
};
#endif
g++ -o p4Driver.cpp
That doesn't say what it's supposed to compile to, which is what -o is supposed to be for. You want:
g++ -c randomNumberMagnifier.cpp
g++ -c p4Driver.cpp
g++ randomNumberMagnifier.o p4Driver.o -o p4Driver
Or just:
g++ randomNumberMangifier.cpp p4Driver.cpp -o p4Driver
you need to provide randomNumberMagnifier.o to g++ command, so it can find function definition. I tested with below command and i worked
g++ -o p4Driver p4Driver.cpp randomNumberMagnifier.o

Error in linking to friend functions

I have a class 'Vector3' which is compiled successfully. It contains both non-friend and friend functions, for example, to overload * and << operators when Vector3 is the second operand. The problem is I can't link to any of the friend functions, be it operator overloaded or not. So I can confirm that the error is not specific to operator overloading. The g++ command used for linking is as follows (please also see Makefile at the end),
g++ -Wall -W -I./ -g -o main.out main.o Vector3.o
which gave the following errors,
main.cpp:7: undefined reference to `operator*(double, Vector3 const&)'
main.cpp:9: undefined reference to `mag(Vector3 const&)'
main.cpp:10: undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Vector3 const&)'
Below is the relevant code in my source files. I follow the practice of making separate .hpp and .cpp for every class.
/* file Vector3.hpp */
struct Vector3 {
...
Vector3 operator*(const double k) const;
friend Vector3 operator*(const double k, const Vector3 &vec);
double magnitude() const;
friend double mag(const Vector3 &vec);
friend std::ostream& operator<<(std::ostream& output, const Vector3 &vec);
...
}
/* file Vector3.cpp */
Vector3 operator*(const double k, const Vector3 &vec) {
...
}
inline double mag(const Vector3 &vec) {
...
}
std::ostream& operator<<(std::ostream& output, const Vector3 &vec) {
...
}
/* file main.cpp */
#include "Vector3.hpp"
int main() {
Vector3 M(1, 1, 1);
M = M * 2.0; // own operator* links successfully
M = 10.0 * M; // friend operator* doesn't link
double m = M.magnitude(); // own function magnitude() links successfully
double n = mag(M); // friend function mag() doesn't link
std::cout << M; // friend operator<< doesn't link
}
Finally, this is my Makefile.
CXX = g++
CXXFLAGS = -Wall -W $(INCPATH) -g
INCPATH = -I./
OBJS = main.o Vector3.o
main.out: $(OBJS)
$(CXX) $(CXXFLAGS) -o $# $(OBJS) $(LIBPATH)
main.o: main.cpp
Vector3.o: Vector3.cpp
clean:
rm -f $(OBJS) main.out
The strangest thing is that if I include the Vector3.cpp file as well in main.cpp and then remove Vector3.o from OBJS in Makefile, the program links successfully. I cannot make sense of this. Please help me!!
The definition of friend operator* uses fp_type while the friend declaration uses double as the first parameter. This will only work as intended if fp_type is a typedef-name for double. Are you sure fp_type actually stands for double? I can't see it from the code you posted.
The problem with mag is rather obvious: you defined it as inline in .cpp file. Inline function definitions have to be visible everywhere they are used, meaning that normally they should be placed in the header file.