2

Hey im using a vector plus its iterator. I have it in the Inventory.h file along with the Inventory.cpp. I want to know is can i call it directly so i can get access to the vector library functions such as push,pop etc... Because at the moment i cant. Can someone help me with this.

Here is my code:

Inventory.h

//-------------------------------------------------------------------------------
//  Inventory.h
//-------------------------------------------------------------------------------

#ifndef INVENTORY_H
#define INVENTORY_H
#include <string>
#include <vector>

using namespace std; 
class Inventory
{
public:
    //Constructor
    Inventory();

    //Methods.
    string add(string item);
    void displayInventory();
    void showInventory();
private:
    //Data members
   vector<string> inventory;
   vector<string>::iterator myIterator;
   vector<string>::const_iterator iter;
    };


#endif //INVENTORY_H

Inventory.cpp

#include "Inventory.h"
#include <iostream>
#include <vector>   //  To enable the use of the vector class.
#include <string>


using namespace std;



Inventory::Inventory()
{

}

string Inventory :: add(string item)
{
inventory.push_back(item);
return item;
}

void Inventory:: showInventory()
{
char input[80];
    cin >> input;
    char inventoryRequest[] = "i";
    int invent = strcmp (input,inventoryRequest);
    //compare the player input to inventoryRequest (i) to see if they want to look at inventory.
    if(invent == 0)
    {
        displayInventory();
    }


}
void Inventory:: displayInventory()
{
//vector<string> inventory;
    cout<< "You have " << inventory.size() << " items.\n";
    cout << "\n******Inventory******";
    cout<< "\nYour items:\n";
    for (int i= 0; i< inventory.size(); ++i)
        cout<< inventory[i] << endl;
}

What i want to be able to do:

int main()
{
Inventory inventory;
inventory.push_back();


}

Errors

Error   2   error LNK2019: unresolved external symbol "public: class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > & __thiscall Inventory::GetContainer(void)" (?GetContainer@Inventory@@QAEAAV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@XZ) referenced in function _main   C:\Users\Conor\Documents\College\DKIT - Year 2 - Repeat\DKIT - Year 2 - Semester 1 - Repeat\Games Programming\MaroonedCA2\MaroonedCA2\Main.obj  MaroonedCA2
Error   3   error LNK1120: 1 unresolved externals   C:\Users\Conor\Documents\College\DKIT - Year 2 - Repeat\DKIT - Year 2 - Semester 1 - Repeat\Games Programming\MaroonedCA2\Debug\MaroonedCA2.exe MaroonedCA2
Pendo826
  • 1,002
  • 18
  • 47
  • Yes, you can rename `Inventory :: add` to `Inventory :: push_back` –  Nov 23 '12 at 13:47
  • inventory.add is the same. But like doing it like this(using the add method) i have not got the ability to use the iterator and i would have to write a function for everything i would like to use from the vector class. – Pendo826 Nov 23 '12 at 13:50

3 Answers3

1

You can inherityour class from std::vector:

class Inventory : public std::vector<std::string> {
   public:
      Inventory();
      void displayInventory();
      void showInventory();
      // [...] 
}

Then in your code you should be able to do things like:

int main()
{
    Inventory inv;
    inv.push_back("item 1");
    inv.push_back("item 2");
    for (Inventor::iterator it = inv.begin(); it != inv.end(); ++it)
           std::cerr << *it << ' ';
    std::cerr << std::endl;
}

Through inheritance you can avoid to redefine methods, iterators and so on.

gabry
  • 1,370
  • 11
  • 26
  • Bad advice. What happens if someone destroys `Inventory` object via `vector` poiner? –  Nov 23 '12 at 13:55
  • @gabry brilliant that is exactly what i wanted to do thanks very much. – Pendo826 Nov 23 '12 at 13:57
  • @Pendo826, just don't come here tomorrow asking "why Inventory class is memory leaking" %) –  Nov 23 '12 at 13:59
  • Warning: http://stackoverflow.com/questions/922248/is-there-any-real-risk-to-deriving-from-the-c-stl-containers – Chubsdad Nov 23 '12 at 13:59
  • @aleguna - Ok is there another way to do it? – Pendo826 Nov 23 '12 at 14:02
  • @aleguna: depending on the use-case there may be little chance of this happening. Are you forbidding to extend any STL class which doesn't have a virtual destructor? – Antoine Nov 23 '12 at 14:02
  • While this will work, and it's even fairly safe in practice because you'll likely not try to delete a instance of this class via a pointer to it's base class, that there is a potential bug there, and also it's generally considered a bad idea to inherit from standard containers for this reason and general style. It'd probably prefered to contain an instance of the vector and then write your own push_back etc that delegate to that instance. – jcoder Nov 23 '12 at 14:02
  • inventory.push_back("Hello"); This does not add Stone to the vector. Whereas my original add function. inventory.add("Sword"); Works. – Pendo826 Nov 23 '12 at 14:03
  • @Pendo826: It looks like you want to give Inventory class the interface of a STL vector. It looks like an 'object Adapter' is what you need. Is this inventory class something that you can't change? – Chubsdad Nov 23 '12 at 14:04
  • @J99 - So writing my own functions is common to do like my add Function ? – Pendo826 Nov 23 '12 at 14:05
  • 2
    @Antoine, I am not forbidding anything, just giving a warning. –  Nov 23 '12 at 14:06
  • @aleguna Memory leaking is something i know nothing about, So i appreciate the advice. – Pendo826 Nov 23 '12 at 14:12
  • @Pendo826, well then you should read about memory in c++ before going any further, topic is too broad to be discussed in comments –  Nov 23 '12 at 14:16
  • 1
    The are not uncommon, and yes they are a pain and a bit ugly, but often better than the alternatives. – jcoder Nov 23 '12 at 14:27
  • @Pendo826 note that private inheritance is much less dangerous than public inheritance here. I would say it is a viable solution here. See my answer. – juanchopanza Nov 23 '12 at 14:40
1

A simple solution is to add a push_back and the other vector methods you want to replicate to your inventory class:

class Inventory
{
public:
    //Constructor
    Inventory();

    //Methods.
    std::string add(std::string item);
    void displayInventory();
    void showInventory();
    void push_back(const std::string& s) { inventory.push_back(s); }
private:
    //Data members
   std::vector<std::string> inventory;
   std::vector<std::string>::iterator myIterator;
   std::vector<std::string>::const_iterator iter;
};

Note that inheriting privately from std::vector could also be an option. It is not 100% safe, but it is hard to find scenarios where it could pose a problem. Inheriting publicly is a definite no-no. This example shows how to expose part of std::vector's privately inherited public interface:

class Inventory : private std::vector<std::string>
{
 public:
  // make a selection of the vector's methods public for this class.
  using std::vector<std::string>::push_back;
  using std::vector<std::string>::pop_back;
  using std::vector<std::string>::begin;
  using std::vector<std::string>::end;
};
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
0

There are many issues/improvement areas with this code snippet. However, for the specific one you asked, please note that 'push_back' is not a member function of Inventory class. So you are getting the compiler error.

You need to call inventory.add for this.

Chubsdad
  • 24,777
  • 4
  • 73
  • 129
  • But like what i mean is, is there anyway i can modify my code so that i can use the push_back function without having to use my add() function. – Pendo826 Nov 23 '12 at 13:52
  • Would it be fine in your case if you provide a 'getter' for the 'inventory' member? – Chubsdad Nov 23 '12 at 13:56
  • Ive never used getters in C++ before. But i dont think there would be a problem with it no. – Pendo826 Nov 23 '12 at 14:08
  • no. no problem language wise. But you would have to evaluate if it is appropriate in your context. So, you can have a member function like std::vector &GetContainer() which returns the reference to the member 'inventory'. Then your call would look like 'Inventory.GetContainer().push_back'. But that does not make it look like 'inventory.push_back' for sure – Chubsdad Nov 23 '12 at 14:12
  • Oh i see and would i put std::vector &GetContainer() in the inventory.h or the inventory.cpp ? – Pendo826 Nov 23 '12 at 14:15