C ++ Java Map Equivalent <String, Object>

In Java, you can create a map that displays String to Generic Object types that can be explicitly passed to other classes. Is there a good way to simulate this functionality in C ++?

+5
source share
2 answers

In C ++ 17, you can use std :: map <std :: string, std :: any> .

+2
source

Being a fairly strongly typed language, C ++ does not have a โ€œGeneric Object Typeโ€. It probably has associative containers: std::map (aroma of a binary tree) and std::unordered_map (taste of a hash table). This is better depending on the use case and often cannot be resolved without profiling.

The closest thing to a shared object that I can think of is a common ancestor for all the objects that can be placed on this map. The idea here is to create a class hierarchy with dynamic polymorphism and save the objects on the map as pointers thrown into this common ancestor. An ideal design would make casting these objects back to their derived class unnecessary. If such selection is required instead, then dynamic_cast will need to be used (and perhaps verify that it succeeded).

Be sure to store pointers on objects on the map, unlike the objects themselves. Otherwise, of the objects that one is trying to insert into the map, only the common part of the ancestor will be saved, and polymorphism will be lost. It is also necessary to decide whether the card belongs to objects or not (there is no garbage here). If not, simple pointers may work. If the map belongs to objects, I would recommend storing them in "unique pointers" ( std::unique_ptr ). Completion:

 #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:

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

(also illustrates the meaning of "unordered" in the name of the card). This example was compiled with g++ -Wall -pedantic -std=c++14 -o test.exe test.cpp (GCC 6.4.0).

+1
source

Source: https://habr.com/ru/post/1270948/


All Articles