I am writing a ROS program and compiling/linking with catkin_make. In a header file, I have defined a class with a virtual method. I then create two sub-classes and implement the virtual method.
class Data {
public:
// TODO change to getter/setter when more CPU power
// becomes available
Data(){}
Data(int8_t state_, ros::Time stamp_) :
state(state_), stamp(stamp_){}
int8_t state,type;
ros::Time stamp;
virtual float* get_data();
};
class GyroData : public Data {
public:
GyroData(const GyroData &other) :
Data(other.state,other.stamp) {
for (int i=0; i<RDR_LEN;i++) {
data[i]=other.data[i];
}
}
GyroData();
float* get_data();
float data[RDR_LEN]; // Data stored as rdr
};
// Usage:
// GyroData gd = new GyroData();
// gd->stamp = ros::Time::now();
// delete gd;
// TODO Be absolutely sure that there are no memory leaks upon
// assigning and destroying map array
class MapData : public Data {
public:
MapData(const MapData &other) :
Data(other.state,other.stamp),len(other.len) {
data = new float[len];
for (int i=0;i<len;i++) {
data[i]=*other.data;
}
}
MapData(int16_t l): len(l) { data = new float[len];}
MapData();
float* get_data();
void free_data();
int16_t len;
float *data; //FIXME change type once decided
};
The virtual method is defined in a cpp file as follows:
float* Data::get_data() {}
I think it is fine for it not to return anything, but I will get a warning. I attempt to use these classes in another file (which includes the correct header file). The variables are declared as follows:
GyroData *px4_r,*px4_r_tmp,*gyro_r,*gyro_r_tmp;
MapData *boundary,*boundary_tmp,*obstacle,
*obstacle_tmp,*target,*target_tmp;
This results in the file not being linked correctly. Upon running catkin_make, I receive an error during linking of
undefined reference to vtable for Data
undefined reference to vtable for GyroData
undefined reference to vtable for MapData
Why is this program not able to link correctly?
Edit:
catkin_make errors:
CMakeFiles/localizer.dir/src/localizer.cpp.o: In function `Localizer::Localizer()':
localizer.cpp:(.text+0x33d): undefined reference to `GyroData::GyroData()'
localizer.cpp:(.text+0x360): undefined reference to `GyroData::GyroData()'
CMakeFiles/localizer.dir/src/localizer.cpp.o: In function `Data::Data()':
localizer.cpp:(.text._ZN4DataC2Ev[_ZN4DataC5Ev]+0x13): undefined reference to `vtable for Data'
CMakeFiles/localizer.dir/src/localizer.cpp.o: In function `Data::Data(signed char, ros::Time)':
localizer.cpp:(.text._ZN4DataC2EaN3ros4TimeE[_ZN4DataC5EaN3ros4TimeE]+0x18): undefined reference to `vtable for Data'
CMakeFiles/localizer.dir/src/localizer.cpp.o: In function `GyroData::GyroData(GyroData const&)':
localizer.cpp:(.text._ZN8GyroDataC2ERKS_[_ZN8GyroDataC5ERKS_]+0x4c): undefined reference to `vtable for GyroData'
CMakeFiles/localizer.dir/src/localizer.cpp.o: In function `MapData::MapData(MapData const&)':
localizer.cpp:(.text._ZN7MapDataC2ERKS_[_ZN7MapDataC5ERKS_]+0x4d): undefined reference to `vtable for MapData'
localizer.cpp:(.text._ZN7MapDataC2ERKS_[_ZN7MapDataC5ERKS_]+0xe2): undefined reference to `Data::~Data()'
CMakeFiles/localizer.dir/src/localizer.cpp.o: In function `MapData::MapData(short)':
localizer.cpp:(.text._ZN7MapDataC2Es[_ZN7MapDataC5Es]+0x26): undefined reference to `vtable for MapData'
localizer.cpp:(.text._ZN7MapDataC2Es[_ZN7MapDataC5Es]+0x7b): undefined reference to `Data::~Data()'
collect2: error: ld returned 1 exit status
make[2]: *** [/home/eric/Documents/AMAV/turtle/devel/lib/terp/localizer] Error 1
make[1]: *** [terp/CMakeFiles/localizer.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
Edit 2: Implementation of Data and subclasses:
#include "terp/state_machine.h"
using namespace std;
// Only implemented so that function is not purely virtual
Data::~Data() {}
// Only implemented so that function is not purely virtual
float* Data::get_data() {}
float* GyroData::get_data() {
return data;
}
GyroData::GyroData() {
for (int i=0;i<RDR_LEN) {
data[i]=0;
}
}
GyroData::~GyroData() {}
float* MapData::get_data() {
return data;
}
MapData::MapData() {
len=1;
data = new float[len];
for (int i=0;i<len;i++) {
data[i]=0;
}
}
MapData::~MapData(){}
void MapData::free_data(MapData d) {
free(d->map);
delete d[];
}