2017-08-17 58 views
5

在Java中,您可以创建一个Map来将String映射到Generic Object类型,这些类型可以明确地转换为其他类。有什么好的方法来模仿C++中的这个功能吗?C++等价的Java Map <String,Object>

+0

有一张地图在C++ 11/14,std :: map。请检查它是否可以满足您的要求。 – tibetty

+0

也[[std :: unordered_map'](http://en.cppreference.com/w/cpp/container/unordered_map) –

+1

我想op是在谈论一个类可以接受任何类型的对象...而不是数据容器集合Map –

回答

1

作为一种相当强类型的语言,C++没有“通用对象类型”。它肯定有关联容器:std::map(二叉树的味道)和std::unordered_map(散列表的味道)。哪一个更好取决于用例,而且如果没有性能分析,往往不能确定。

我能想到的最接近通用对象的东西是可能放入此地图的所有对象的共同祖先。这里的想法是创建一个具有动态多态性的类层次结构,并将映射中的对象存储为指向该共同祖先的指针。 理想的设计将使这些对象转换回它们的派生类是不必要的。如果需要这种转换,则必须使用dynamic_cast(并且可能检查它是否成功)。

必须将指针存储到地图中的对象,而不是对象本身。否则,在试图插入地图的对象中,只有共同的祖先部分将被存储,并且多态性将会丢失。还需要决定地图是否拥有对象(这里没有垃圾回收)。如果不是,简单的指针可能工作。如果地图拥有对象,我建议将它们存储在“独特指针”(std::unique_ptr)中。 结束语:

#include <unordered_map> 
#include <string> 
#include <memory> // std::unique_ptr<>, std::make_unique() 
#include <iostream> 

class NotSoGenericClass { 
    public: 
    virtual ~NotSoGenericClass() = default; 
    virtual std::string name() const 
    { return "NotTooGenericClass()"; } 
}; 

class EvenLessGenericClass: public NotSoGenericClass { 
    int fValue = 0; 
    public: 
    EvenLessGenericClass(int value): fValue(value) {} 
    virtual std::string name() const override 
    { return "EvenLessGenericClass(" + std::to_string(fValue) + ")"; } 
    int value() const { return fValue; } 
}; 

int main() { 
    // 
    // map holding (and owning) "not so generic objects" 
    // 
    std::unordered_map<std::string, std::unique_ptr<NotSoGenericClass>> allObjects; 

    // 
    // populate it 
    // 
    allObjects["any"] = std::make_unique<NotSoGenericClass>(); 
    allObjects["six"] = std::make_unique<EvenLessGenericClass>(6); 
    allObjects["one"] = std::make_unique<EvenLessGenericClass>(1); 

    std::cout << "Object 'six' says: " << allObjects["six"]->name() << std::endl; 

    std::cout << "Now dumping all " << allObjects.size() << " objects:"; 
    for (auto const& keyAndObject: allObjects) { 

    auto const& key = keyAndObject.first; 
    auto const* object = keyAndObject.second.get(); 

    // 
    // base class interface is always available: 
    // 
    std::cout << "\n[" << key << "] " << object->name(); 

    // 
    // object-specific one requires a cast: 
    // 
    auto const* lessGen = dynamic_cast<EvenLessGenericClass const*>(object); 
    if (lessGen) std::cout << " (value is " << lessGen->value() << ")"; 

    } // for 
    std::cout << std::endl; 

    return 0; 
} // main() 

在我的平台,该代码(使用C++ 14)发射:

[one] EvenLessGenericClass(1) (value is 1) 
[six] EvenLessGenericClass(6) (value is 6) 
[any] NotTooGenericClass() 

(也示出在地图名称 “无序” 的意思)。 本示例编译为g++ -Wall -pedantic -std=c++14 -o test.exe test.cpp(GCC 6.4.0)。

2

在C++ 17中,您可以使用std :: map < std :: string,std :: any >

相关问题