0

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[];
}
errolflynn
  • 641
  • 2
  • 11
  • 24
  • 1
    Are you sure you're linking in all the object files? Posting a full program to reproduce this would be best, though. – xaxxon Mar 25 '16 at 05:08
  • 1
    Not returning anything from a function is undefined behavior. – Anton Savin Mar 25 '16 at 05:34
  • See http://stackoverflow.com/questions/3065154/undefined-reference-to-vtable – Anton Savin Mar 25 '16 at 05:40
  • You need to provide a body for `Data::get_data()`, and `GyroData::get_data()`, and `MapData::get_data()` – M.M Mar 25 '16 at 05:50
  • 1
    `Data` should have virtual destructor, if you intended to delete a pointer to base class – M.M Mar 25 '16 at 05:51
  • @AntonSavin I have created a test program, in which a Base class virtual method doesn't return anything. Since that method will never be called, and the Derived class function will always override the virtual method, I believe this method definition is alright. The compiler only issues a warning. – errolflynn Mar 25 '16 at 15:56
  • @M.M I have provided a body for each of the three get_data methods. – errolflynn Mar 25 '16 at 16:38
  • 1
    Are you sure that you're actually building the file which provides Gyrodata::Gyrodata()? – rubenwardy Mar 25 '16 at 17:46
  • It was a mistake with the CMakeLists.txt file. I wasn't linking correctly. Thank you! – errolflynn Mar 25 '16 at 18:33

0 Answers0