C++工厂制造和多态性 ->调用由映射迭代器访问的实例的子类的虚拟方法

C++ factory made and polymorphism -> invoke subclass's virtual method of an instance accessed by a map's iterator

本文关键字:访问 迭代器 映射 实例 方法 虚拟 子类 调用 制造 工厂制 工厂      更新时间:2023-10-16

我有一个关于多态性的问题。

这是我代码的重要部分。

如果我的问题很愚蠢,我很抱歉,但我不明白如何在这种方法中使用多态性:

Val_Type Sensor_Map::Get_Last_Value(const std::string &_Nome_Fisico) const

我知道return iter->second.Get_Last_Value();不正确,因为多态性仅在通过指针访问该方法时才有效。我尝试这样做:

        const Sensor *S = &(iter->second);
        return S->Get_Last_Value();

但它在temperature_Sensor方法中调用传感器的方法。 当我做Sensori.insert(std::pair<std::string, Sensor>(_Nome_Fisico, *S));时,问题会在工厂制造内部吗?在这种情况下,我应该在实例中存储一个指针(并更改很多代码:((,但是在SensorMap::Insert()结束时,新实例超出了范围,我可以有悬空指针吗?

 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
            }
    }

非常感谢您的耐心等待,有好的一天

首先

需要在Sensori地图中存储指针。也就是说,它应该是 std::map<std::string,Sensor*> 型或更好的 std::map<std::string, std::shared_ptr<Sensor>> .更喜欢第二种变体,因为它让您不必担心内存泄漏和过早释放对象,从而使您的生活更加轻松。

您的程序现在存在在Sensori中插入Temperature_Sensor时对象切片的问题。您的Sensori地图现在存储Sensor对象,而不是任何传感器子类型的对象。现在获取存储对象的地址并希望它指向Temperature_Sensor有点晚了。您分配的Temperature_Sensor已被切掉,仅此而已。

代码类似

Sensor *S = Sensor(_Nome_Fisico);
Sensori.insert(std::pair<std::string, Sensor>(_Nome_Fisico, *S));
delete S;       // deallocazione memoria dinamica

可以这样表达

Senor S(whatever);
Sensori.insert(std::pair<std::string, Sensor>(whatever, S));
// no delete

但无论如何都是错误的(见上文关于对象切片的信息(,你需要这个

std::shared_ptr<Sensor> S (std::make_shared<Sensor>(whatever));
Sensori[whatever] = S; // note no verbose iterator syntax
// no delete, ever

最后但并非最不重要的一点是,不要使用前导下划线后跟大写字母(如_Nome_Fisico(,因为此类名称是为实现保留的。