实现使用 C++ 存储任何类型的哈希

Implementing a hash which stores any type using C++

本文关键字:类型 哈希 任何 存储 C++ 实现      更新时间:2023-10-16

在我正在开发的库中,我有一个类,我想有一个哈希来存储任何类型的数据。这是因为使用此库的算法可能希望在该类的对象中存储特定数据。

该类称为"ObjectOfInterest",我在其中使用QT定义了哈希:

QHash<QString, void*> properties;

然后我实现了这个函数来存储信息:

bool ObjectOfInterest::hasProperty(QString prop) const
{
    return properties.contains(prop);
}
template <class T> const T& ObjectOfInterest::getProperty(const QString prop) const
{
    return *(T *)properties.value(prop);
}
template <class T> void ObjectOfInterest::setProperty(const QString prop, T value)
{
    if (hasProperty(prop)) deletePropertyValue<T>(prop);
    properties.insert(prop, new T(value));
}
//private
template <class T> void ObjectOfInterest::deletePropertyValue(const QString prop)
{
    delete (T *)properties.value(prop);
}

现在的问题是,在删除"ObjectOfInterest"的对象时,如何删除存储在属性哈希中的所有值?现在我有

ObjectOfInterest::~ObjectOfInterest()
{
    //delete other stuff...
    QHash<QString, void*>::iterator i;
    for (i = properties.begin(); i != properties.end(); ++i)
    {
        delete i.value();
    }
}

但这不是解决方案,因为我没有调用析构函数。任何想法如何做到这一点?

谢谢!

因此,与其使用 void* ,我会创建一个包装类,可以在其中容纳其他对象,或者从同一个基类中派生所有"感兴趣的对象内容"。你喜欢哪一个将取决于你。

我建议这样做的原因是,当你使用数据时,你会希望它是可识别的,而通过拥有一个对象类型来提供相关的接口来做到这一点似乎很愚蠢。

换句话说,如果你存储一些东西,你想"标记它",以便你知道它是什么。就像你在车库、阁楼或任何存放你暂时不需要但想留给未来的东西的地方所做的那样。例如,你有一个盒子,上面写着"旧鞋"或"冬衣","婴儿衣服","书籍"等[除非你像我一样,你只有一堆类似的盒子,不知道哪个盒子里有什么 - 但那是因为我的存储不是作为软件完成的]。

最后的解决方案是使用 boost::any

//ObjectOfInterest.h
public:
    ...
    bool    hasProperty(const string & prop) const;
    void    emplaceProperty(const string & prop, boost::any value);
    void    setProperty(const string & prop, boost::any value);
    template <class T> const T property(const string & prop) const
    {
    return any_cast<T>(properties.at(prop));
    }
...
private:
    ...
    boost::unordered::unordered_map<string, boost::any> properties;

//ObjectOfInterest.cpp
...
bool ObjectOfInterest::hasProperty(const string & prop) const
{
    return properties.find(prop)!=properties.end();
}
void ObjectOfInterest::emplaceProperty(const string & prop, any value)
{
    properties.emplace(prop, value);
}
void ObjectOfInterest::setProperty(const string & prop, any value)
{
    properties[prop] = value;
}