在Java中,您可以创建一个将字符串映射到通用对象类型的Map,这些对象类型可以明确地转换为其他类。在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()
[one] EvenLessGenericClass(1) (value is 1)
[six] EvenLessGenericClass(6) (value is 6)
[any] NotTooGenericClass()
(同时说明了地图名称中“unordered”的含义)。此示例是使用g++ -Wall -pedantic -std=c++14 -o test.exe test.cpp
(GCC 6.4.0)编译的。
std::unordered_map
- phuclvstd::any
。或者只是一个普通的void*
。如果不知道你计划如何使用这个东西,很难说。 - Igor TandetnikMap <String,Object>
,因为C ++类型系统本身在根本上有太大的区别。例如,Map <String,Object>
是一个java泛型,基本上是具有语法糖的Map <Object,Object>
并且是一个基类。C ++中的std :: map <std :: string,Foo>
是一个一级对象,它确实具有std :: string键。此外,在C ++中没有等价于“Object”的东西,尽管有弱类型/包装器。 - H WaltersMap<String,Object>
时有一个特定的问题需要解决,那么在C++中也很可能有至少一种特定的方法来解决这个问题;然而,通常情况下,我能够想到至少5种不同的方法来“模拟”它们(并且它们都是不同的)。 - H Walters