I want to use a C++ map
of function to execute some subroutines.
Since, such a map of function requires to have the same type of input and output for all the mapped functions, while my functions can have different input type, I though I could made all these different types derive from a SuperParentClass
.
However, this idea gives me some troubles. It does not compile. Indeed, the compiler capture the derived type and not the parent class. But if you I directly the parent class in my functions, I won't be able to use their specialties inside my functions (so I come for help).
Here is my MWE:
#include <functional>
#include <iostream>
#include <map>
#include <string>
#include <math.h>
class SuperParentClass
{
private:
/* data */
public:
std::string nameClass;
};
class ChildClassRectangle : public SuperParentClass
{
private:
/* data */
public:
int longueur=2;
int largeur=2;
};
class ChildClassCircle : public SuperParentClass
{
private:
/* data */
public:
int radius=2;
};
int areaRect(ChildClassRectangle rect)
{
std::cout << "areaRect "<< rect.largeur*rect.longueur << std::endl;
return 0;
}
int areaCircle(ChildClassCircle circ)
{
std::cout << "areaCircle "<< 3.14*pow(circ.radius,2) << std::endl;
return 0;
}
int main()
{
std::cout << "TEST " << std::endl;
std::map<std::string, SuperParentClass> mapObject;
ChildClassCircle circ;
circ.radius=2;
mapObject["Circle"]=circ;
ChildClassRectangle rect;
rect.longueur=1;
rect.largeur=3;
mapObject["Rectangle"]=rect;
using CallFunc = std::function<int(SuperParentClass)>;
std::map<std::string, CallFunc> mapFunction;
// mapFunction["Circle"]=areaCircle;
// mapFunction["Rectangle"]=areaRect;
// mapFunction["Circle"](mapObject["Circle"]);
// mapObject["Rectangle"].largeur=4;
// mapFunction["Rectangle"](mapObject["Rectangle"]);
};
The last 5 lines are commented are what I want to do that is not working.
Rather than having a map go to functions it can map to a SuperParentClass pointer. Then use a virtual function in each class to encapsulate the desired behavior.
int areaRect(ChildClassRectangle rect);
int areaCircle(ChildClassCircle circ);
class SuperParentClass
{
public:
virtual int area() = 0;
... // more code...
};
class ChildClassRectangle : public SuperParentClass
{
public:
virtual int area() override
{
return areaRect(*this);
}
... // more code...
};
class ChildClassCircle : public SuperParentClass
{
public:
virtual int area() override
{
return areaCircle(*this);
}
... // more code...
};
To eliminate the pass by value of classes, simply move the functions into the area() functions.
Now function calls are directly available without a separate map.
Here is a rough version that probably doesn't work exactly; but conveys the idea.
void main()
{
std::map<std::string, SuperParentClass*> mapObject;
...
mapObject["Circle"]=ˆ
...
mapObject["Rectangle"]=▭
...
const int circleReturn = mapObject["Circle"]->area();
// Cannot access derived properties here
// mapObject["Rectangle"]->largeur=4; // No longer valid.
const int rectReturn = mapObject["Rectangle"]->area();
}
Pointers aren't required here; as objects can be emplaced on the container; or some other type of data structuring. This is simply meant to show using a virtual function is a simpler approach and better design.