在Java中,您可以创建一个Map,将String映射到可以显式转换为其他类的Generic Object类型。有没有什么好的方法可以在C ++中模仿这个功能?
答案 0 :(得分:3)
在C ++ 17中,你可以使用 std :: map< std :: string,std :: any> 。
答案 1 :(得分: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)编译。