简体   繁体   English

C ++等效的Java Map <String, Object>

[英]C++ Equivalent of Java Map<String, Object>

In Java you can create a Map that maps String to Generic Object types that can be explicitly casted to other classes. 在Java中,您可以创建一个Map,将String映射到可以显式转换为其他类的Generic Object类型。 Is there any nice way of imitating this functionality in C++? 有没有什么好的方法可以在C ++中模仿这个功能?

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

Being a quite strongly typed language, C++ does not have a "Generic Object Type". 作为一种非常强类型的语言,C ++没有“通用对象类型”。 It surely has associative containers: std::map (a flavour of binary tree) and std::unordered_map (a flavour of hash table). 它肯定有关联容器: std::map (一种二叉树的味道)和std::unordered_map (一种哈希表的味道)。 Which is better depends on the use case, and often can't be decided without profiling. 哪个更好取决于用例,并且通常不能在没有分析的情况下决定。

The closest thing to a generic object I can think of is a common ancestor for all the objects that might be put in this map. 我能想到的最接近通用对象的东西是可能放在这个地图中的所有对象的共同祖先。 Here the idea is to create a class hierarchy with dynamic polymorphism, and to store the objects in the map as pointers cast into that common ancestor. 这里的想法是创建一个具有动态多态性的类层次结构,并将对象存储在地图中作为投射到该共同祖先的指针。 The ideal design would make casting of these objects back to their derived class unnecessary. 理想的设计会使这些对象无法转换为派生类。 If instead such cast is required, one will have to use a dynamic_cast (and possibly check that it succeeded). 如果需要这样的强制转换,则必须使用dynamic_cast (并且可能检查它是否成功)。

It is mandatory to store pointers to the objects in the map, as opposed to the objects themselves. 必须存储指向地图中对象的指针 ,而不是对象本身。 Otherwise, of the objects one tries to insert into the map, only the common ancestor part would be stored, and the polymorphism would be lost. 否则,在试图插入到地图中的对象中,只存储共同的祖先部分,并且多态性将丢失。 It also needs to be decided whether the map owns the objects or not (no garbage collection here). 还需要确定地图是否拥有对象(此处没有垃圾收集)。 If not, simple pointers may work. 如果没有,简单的指针可能会起作用。 If the map owns the objects, I would recommend storing them wrapped in "unique pointers" ( std::unique_ptr ). 如果地图拥有对象,我建议将它们包含在“唯一指针”( std::unique_ptr )中。 Wrapping up: 包起来:

#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()

On my platform, this code (using C++14) emits: 在我的平台上,此代码(使用C ++ 14)发出:

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

(also illustrating the meaning of "unordered" in the map name). (也说明了地图名称中“无序”的含义)。 This example was compiled with g++ -Wall -pedantic -std=c++14 -o test.exe test.cpp (GCC 6.4.0). 此示例使用g++ -Wall -pedantic -std=c++14 -o test.exe test.cpp (GCC 6.4.0) g++ -Wall -pedantic -std=c++14 -o test.exe test.cpp

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM