I have a question about polymorphism.
Here is the significant piece of my code.
I'm sorry if my question is stupid, but i can't understand how can I use polymorphism in this method:
Val_Type Sensor_Map::Get_Last_Value(const std::string &_Nome_Fisico) const
I know that return iter->second.Get_Last_Value();
is not correct, because polymorphism work only if the method is accessed by pointer.
I've try to make this:
const Sensor *S = &(iter->second);
return S->Get_Last_Value();
but it call the method of Sensor inside the temperature_Sensor
method. can the problem be inside factory made when I do Sensori.insert(std::pair<std::string, Sensor>(_Nome_Fisico, *S));
?
In this case, I should store a pointer inside the instance (and change a lot of code :( ), but at the end of SensorMap::Insert()
the new instance goes out of scope I can have dangling pointer?
typedef float Val_Type;
class Sensor
{
private:
Val_Type Last;
........
public:
virtual Val_Type Get_Last_Value() const;
........
};
class Temperature_Sensor:public Sensor
{
........
public:
Val_Type Get_Last_Value() const;
........
};
Val_Type Sensor::Get_Last_Value() const
{return Last;}
Val_Type Temperature_Sensor::Get_Last_Value() const
{ return ((Last * (Tempeartura_Max - Tempeartura_Min) / 1024) + Tempeartura_Min );}
class Sensor_Map
{
private:
........
std::map<std::string,Sensor>Sensori;
public:
........
inline Val_Type Get_Last_Value(const std::string &_Nome_Fisico) const;
};
void Sensor_Map::Insert(const std::string &_Nome_Fisico)
{
// FACTORY MADE for sensor type
char type;
type=_Nome_Fisico[0]; // first character set the type
switch(type)
{
case 's':
{ // creo un nuovo sensore base
Sensor *S = new Sensor(_Nome_Fisico);
Sensori.insert(std::pair<std::string, Sensor>(_Nome_Fisico, *S));
delete S; // deallocazione memoria dinamica
break;
}
case 't':
{ // creo un nuovo Temperature_Sensor
Sensor *S = new Temperature_Sensor(_Nome_Fisico);
Sensori.insert(std::pair<std::string, Sensor>(_Nome_Fisico, *S));
delete S; // deallocazione memoria dinamica
break;
}
}
}
Val_Type Sensor_Map::Get_Last_Value(const std::string &_Nome_Fisico) const
{
std::map<std::string,Sensor>::const_iterator iter = Sensori.find(_Nome_Fisico);
if(iter !=Sensori.end())
{ // <== MY PROBLEM IS HERE ####################################
// i would like to return the member "Last" of the sensor pointed by iter->second through the more specific methods
}
}
thank you very much for your patience, have a nice day
You need to store pointers in your Sensori
map in the first place. That is, it should be of type std::map<std::string,Sensor*>
or better yet std::map<std::string, std::shared_ptr<Sensor>>
. Prefer the second variant as it makes your life much much easier by making you not worry about memory leaks and premature freeing of objects.
Your program as it stands now has the problem of object slicing when you insert a Temperature_Sensor
in Sensori
. Your Sensori
map stores Sensor
objects now, and not objects of any sensor subtype. It's a bit late to take an address of a stored object and hope it will point to a Temperature_Sensor
. The Temperature_Sensor
you have allocated has been sliced away, it is no more.
Code like
Sensor *S = Sensor(_Nome_Fisico);
Sensori.insert(std::pair<std::string, Sensor>(_Nome_Fisico, *S));
delete S; // deallocazione memoria dinamica
could be expressed like this
Senor S(whatever);
Sensori.insert(std::pair<std::string, Sensor>(whatever, S));
// no delete
but it is wrong anyway (see above about object slicing) and you need this
std::shared_ptr<Sensor> S (std::make_shared<Sensor>(whatever));
Sensori[whatever] = S; // note no verbose iterator syntax
// no delete, ever
Last but not least, do not use a leading underscore followed by a capital letter (as in _Nome_Fisico
) because such names are reserved for the implementation.