1

I am training to encapsulate some codes and for this I created three classes, which are Vero, Pionner and Vehicle. The first two classes have the member variable cmd and the member function getcmd - in each classes theses members are slightly different. Then. we have the class Vehicle, which is a subclass of Vero and Pionner. The Vehicle constructor has the parameter which_car that should be used to select which of the two classes we want to work with.

I would like to have some kind of function pointer that could point to the getcmd member function of the class Vero or of the class Pionner. How could a perform this task?

COMMENT: I am not asking about how to just create a member point. I am asking how can I, somehow, create a generic type that can point or to Vero objects or to Pionner objects.

The code I am working on.

HEADER

#ifndef VEHICLE_H
#define VEHICLE_H

#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <ransac_project/CarCommand.h>


class Vero{
public:
    ransac_project::CarCommand cmd;

    Vero();
    void getcmd(const double &velocity, const double &steering);
};


class Pionner{
public:
    geometry_msgs::Twist cmd;

    Pionner();
    void getcmd(const double &linear_vel, const double &angular_vel);
};


class Vehicle: public Vero, public Pionner{
public:
    Vehicle(const std::string &which_car);
    void (*arrangemessage) (const double &, const double &);
};

#endif /* VEHICLE_H */

SOURCE

#include "vehicle.hpp"

Vero::Vero(){
    cmd.speedLeft  = 0.0; cmd.speedRight = 0.0; cmd.steerAngle = 0.0;
    return;
}

void Vero::getcmd(const double &velocity, const double &steering){
    cmd.speedLeft  = velocity;
    cmd.speedRight = velocity;
    cmd.steerAngle = steering;
    return;
}

Pionner::Pionner(){
    cmd.linear.x  = 0.0; cmd.linear.y  = 0.0; cmd.linear.z  = 0.0;
    cmd.angular.x = 0.0; cmd.angular.y = 0.0; cmd.angular.z = 0.0;
    return;
}

void Pionner::getcmd(const double &linear_vel, const double &angular_vel){
    cmd.linear.x = linear_vel;
    cmd.linear.y = 0;
    cmd.linear.z = 0;
    cmd.angular.x = 0;
    cmd.angular.y = 0;
    cmd.angular.z = angular_vel;
    return;
}


Vehicle::Vehicle(const std::string &which_car){
    if(which_car.compare("vero")==0){
        arrangemessage = &Vero::getcmd;
    }
    else if(which_car.compare("pionner")==0){
        arrangemessage = &pionner.getcmd;
    }
    else{
        ROS_INFO_STREAM("which_car must be vero or pionner");
        exit(0);
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Randerson
  • 775
  • 1
  • 5
  • 19
  • why you have your title as tags ? – HazemGomaa Oct 03 '16 at 16:25
  • Instead of naming things that exist, write a title that summarises your question, just like everyone else does! – Lightness Races in Orbit Oct 03 '16 at 16:28
  • 1
    I'm not quite sure what `Vero` and `Pionner` are supposed to be, but the notion that every vehicle is both a Vero and a Pionner seems weird. – Baum mit Augen Oct 03 '16 at 16:29
  • 1
    If Vero and Pionner are supposed to be different kinds of Vehicles, you have your inheritance backwards: Each of the former should derive from the latter. – Baum mit Augen Oct 03 '16 at 16:32
  • We can change the name... Let's think about SelectedVehicle. – Randerson Oct 03 '16 at 16:34
  • You can't have a variable whose type is also variable. – molbdnilo Oct 03 '16 at 16:36
  • Parent & child classes generally have an `is-a` relationship, where the child is a specialised case of the parent. For example, `Car` & `Plane` would generally be subclasses of `Vehicle`, while `Porsche` & `Pinto` could be subclasses of `Car`. In your case, since both versions of `getcmd()` share the same signature, it would probably be best to make `Vehicle` the base class, with `getcmd()` as a virtual function. `Vero` and `Pionner` would then inherit from `Vehicle`, and have their own implementations of `getcmd()`. You could then use a `Vehicle*` that points to a `Vero` or a `Pionner`. – Justin Time - Reinstate Monica Oct 03 '16 at 16:51
  • Alternatively, you could use SFINAE, and make `Vehicle` a template type that takes a class with member function `getcmd()` as the template parameter. Using a second parameter, which is `void` by default, or [`void_t`](http://stackoverflow.com/documentation/c%2b%2b/1169/sfinae-substitution-failure-is-not-an-error/3778/void-t#t=201610031653020301236) for classes with `getcmd()`, we can do [this](http://ideone.com/N7anM8). This is a bit backwards from a design standpoint, IMO, but fits what you wanted better (without a function pointer). – Justin Time - Reinstate Monica Oct 03 '16 at 17:17

0 Answers0