C++ Equivalent of Java Map<String, Object>

C++ Equivalent of Java Map<String, Object>

本文关键字:String Object gt Equivalent lt Java Map C++ of      更新时间:2023-10-16

在Java中,你可以创建一个Map,将String映射到可以显式强制转换为其他类的泛型对象类型。有什么好方法可以在C++中模仿此功能吗?

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

作为一种非常强的类型语言,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( 编译的。