views:

128

answers:

3

Is there any practical way to get objects to work with maps? (I don't really know much about maps so sorry if this is a bad question). I'm interested in using a map for an inventory system that will contain item objects. An item object has a name, description, and money value. The key would be the item's name, and the linking variable would be the the quantity of items I have for that particular item.

And if a map doesn't work, does anyone have a good alternative to this type of system? I need something keeping track of the quantity of each type of item I have.

+3  A: 

If you're talking about std::map, it's a template which can work with any type of object, as long as a way to compare objects for ordering is provided. Since your key (the name) is a string, it will work right out of the box with std::map

struct Item
{
    std::string description;
    int value;
};


int main()
{
    // associate item names with an item/quantity pair
    std::map<std::string, std::pair<Item, int> > itemmap;
}
Charles Salvia
the problem is that my Item is a class (trying to make it reusable for future games, and I plan on subclassing from it)
graydragon10
Why is that a problem?
Charles Salvia
@graydragon - you can create a class that has a reference to an item and an int for the quantity. the basic structure will still be the same - namely a map with key as item name pointing to one of these classes.
SB
@graydragon. Seem my example above for a map that takes a class as its templated parameter.
Jason R. Mick
I think I understand what he might mean. As you can't put objects of a derived type in a map lest they be truncated (A derives from B, putting a B in `map<A>` will give surprising results to the uninitiated.) You have to use pointers, or some kind of other reference if you want to mix instances with a common base. Maybe this is what graydragon wants to avoid? Or perhaps he has misunderstood the workings of the type system. Just grasping straws here :)
Skurmedel
+1  A: 

I need something keeping track of the quantity of each type of item I have.

How about std::vector<std::pair<Item, int> >?

FredOverflow
Would this work if I only want each item type to appear in the list once? like apples - 5, oranges - 2, etc.
graydragon10
+4  A: 

The Standard Template Library (STL) map is just a storage container so it can definitely be used with objects. The map will take your object as its templated argument parameter

A map would work well for your inventory system. Use something like

#include <pair>
#include <map>
#include <string>
#include <iostream>

class Item {
  public:
   Item(void) {}
   ~Item(void) {}
   Item(std::string new_name) {
      my_name=new_name;
   }
   void setName(std::string new_name) {
      my_name= new_name;
   }
   std::string getName(void) {
      return my_name;
   }
  private:
   std::string my_name;
};  

class Item_Manager {
  public:
   Item_Manager(void) {}
   ~Item_Manager(void) {}  
   void addItem(Item * my_item, int num_items) {
      my_item_counts.insert( std::pair<std::string,int>(Item.getName(),num_items) );
   }
   int getNumItems(std::string my_item_name) {
      return my_item_counters[my_item_name];
   }
  private: 
   std::map<std::string, int> my_item_counts;
};

main () {
   Item * test_item = new Item("chips");
   Item * test_item2 = new Item("gum");
   Item_Manager * my_manager = new Item_Manager();

   my_manager->addItem(test_item, 5);
   my_manager->addItem(test_item2,10);
   std::cout << "I have " << my_manager->getNumItems(test_item->getName())
             << " " << test_item->getName() << " and " 
             << my_manager->getNumItems(test_item2->getName())
             << " " << test_item2->getName() << std::endl;

   delete test_item;
   delete test_item2;
   delete my_manager;
}

This is a good reference on the STL map and its functions: http://www.cplusplus.com/reference/stl/map/

Look at the function pages for examples of how to iterate through/index a map, etc.

Jason R. Mick
I wanted <std::Item.getName(), int> and it complained to me. is there a good workaround?
graydragon10
Your Item class should not be in the namespace standard. You're confusing assignment and declaration. See my above edits in a sec.
Jason R. Mick
graydragon10: the type parameters of `std::map` are decided compile time. I suspect `getName` returns a `std::string`? If so you should declare it `std::map<std::string, int>`.
Skurmedel
oh I see now! let me try getting this implemented, thank-you
graydragon10
Alright I made a full class driven example that I believe satisfies your above listed use request!
Jason R. Mick
this looks great. I'm just wondering where my_item_counters is coming from? I don't see where it was declared.
graydragon10