-2

Hey guys I was working on a board game and implementing its table till I got this error.

class Grid {
private:
    int     size;
    char**  grid;
    int noofsupplies; //determined by the grid size.
    vector<Food*> food;
    vector<Water*>  water; //Used 4 different vector to keep track of every kind of object easier.
    vector<Mine*> mine;
    vector<Medical*> medical;
public:
    Grid(int sizeofgrid) {
        size = sizeofgrid;
        noofsupplies = 3 * (pow(sizeofgrid, 2) / 25);
        grid = new char*[size];
        for (int i = 0;i < size;i++)
            grid[i] = new char[size];
        for (int i = 0;i < size;i++) {
            for (int j = 0;j < size;j++)
                grid[i][j] = '-';
        }
        Resources* f = new Food();
        Resources* w = new Water();
        Resources* m = new Mine();
        Resources* s = new Medical();
        for (int i = 0;i < noofsupplies;i++) {
            food.push_back(*f);
            water.push_back(*w);
            mine.push_back(*m);
            medical.push_back(*s);
        }

        deploy_resources(); //place the food inside the map..
    }

But it gives the error:

Severity Code Description Project File Line Suppression State Error (active) no instance of overloaded function "std::vector<_Ty, _Alloc>::push_back [with _Ty=Food *, _Alloc=std::allocator]" matches the argument list

What can be the reason?

Hunter Turner
  • 6,804
  • 11
  • 41
  • 56
  • already tried it didnt work :( – Ballsy Coder May 26 '16 at 21:29
  • Those are vectors of pointers... – LogicStuff May 26 '16 at 21:30
  • `vector food;` expects you to `push_back` a `Food *`. `*f` is a `Food`, not a `Food *`. If you `push_back` `f` then that line will work. – nwp May 26 '16 at 21:32
  • @AlexD but Resources is an abstract class for my food water mine and medicals so i should use it when defining a new resource then specify the type.. – Ballsy Coder May 26 '16 at 21:32
  • On another note: avoid `new`, you have memory leaks everywhere and there is no reason to use pointers. It makes much more sense to use `vector food; Food f; food.push_back(f);` – nwp May 26 '16 at 21:34
  • `(pow(sizeofgrid, 2) / 25);` Do not use `pow` to compute integer powers. [There is no guarantee you will get the desired results](http://stackoverflow.com/questions/25678481/why-pown-2-return-24-when-n-5/25678721#25678721) – PaulMcKenzie May 26 '16 at 21:35
  • @nwp But as I said above resources is my abstract class shouldnt i use it when creating a new object of type abstract class ? – Ballsy Coder May 26 '16 at 21:36
  • @nwp Actually the type of `f` is `Resource*` and the type of `*f` is `Resource&`. The vector's won't accept it either unless `Resource` is a subclass of `Food`, `Water`, `Mine`, and `Medical`. – Edward Strange May 26 '16 at 21:37
  • @BallsyCoder Your code has memory leaks. You lose the pointer values returned to you from `new`, thus never getting the chance to free the memory. – PaulMcKenzie May 26 '16 at 21:37

2 Answers2

2

food is a vector of pointers to Food, not a vector of Resources objects.

You can do this:

        Food* f = new Food();
        Water* w = new Water();
        Mine* m = new Mine();
        Medical* s = new Medical();
        for (int i = 0;i < noofsupplies;i++) {
            food.push_back(f);
            water.push_back(w);
            mine.push_back(m);
            medical.push_back(s);
        }

But you are just putting noofsupplies different copies of the same pointer, pointing to the same object. You can get the same effect by just doing

food.insert(food.begin(), noofsupplies, f);
water.insert(water.begin(), noofsupplies, w);
mine.insert(mine.begin(), noofsupplies, m);
medical.insert(medical.begin(), noofsupplies, s);

instead of the loop.

But having the same object many times is probably not what you want. If they should all be different objects, have your loop do

        for (int i = 0; i < noofsupplies; i++) {
            food.push_back(new Food());
            water.push_back(new Water());
            mine.push_back(new Mine());
            medical.push_back(new Medical());
        }

Or, if they don't need to be pointers at all, just have vector<Food>, etc., instead of vectors of pointers.

Nick Matteo
  • 4,453
  • 1
  • 24
  • 35
1

The problem is that your push_back() calls are not pushing the correct values that the various vectors are expecting.

vector<Food*> expects you to push_back() a Food* but you are trying to push a Resource* instead.

vector<Water*> expects you to push_back() a Water* but you are trying to push a Resource* instead.

vector<Mine*> expects you to push_back() a Mine* but you are trying to push a Resource* instead.

vector<Medical*> expects you to push_back() a Mine* but you are trying to push a Resource* instead.

Yes, you are creating objects of type Food, Water, Mine and Medical, respectively. But you are assigning all of them to Resource* variables, and that is where the error is originating from. None of your vectors are expecting Resource*.

Try this instead:

class Grid {
private:
    int size;
    char** grid;
    int noofsupplies; //determined by the grid size.
    vector<Food*> food;
    vector<Water*> water;
    vector<Mine*> mine;
    vector<Medical*> medical;
public:
    Grid(int sizeofgrid)
        : size(0), grid(NULL), noofsupplies(0)
    {
        size = sizeofgrid;
        noofsupplies = 3 * ((sizeofgrid * sizeofgrid) / 25);
        grid = new char*[size];
        for (int i = 0; i < size;i++)
            grid[i] = new char[size];
        for (int i = 0; i < size; ++i) {
            for (int j = 0; j < size; ++j)
                grid[i][j] = '-';
        }
        for (int i = 0; i < noofsupplies; ++i) {
            food.push_back(new Food);
            water.push_back(new Water);
            mine.push_back(new Mine);
            medical.push_back(new Medical);
        }

        deploy_resources(); //place the food inside the map..
    }

    Grid(const Grid &src)
        : size(0), grid(NULL), noofsupplies(0)
    {
        size = src.size;
        noofsupplies = src.noofsupplies;
        grid = new char*[size];
        for (int i = 0; i < size; ++i)
            grid[i] = new char[size];
        for (int i = 0; i < size; ++i) {
            for (int j = 0; j < size; ++j)
                grid[i][j] = src.grid[i][j];
        }
        for (int i = 0; i < noofsupplies; ++i) {
            food.push_back(new Food(*(src.food[i])));
            water.push_back(new Water(*(src.water[i])));
            mine.push_back(new Mine(*(src.mine[i])));
            medical.push_back(new Medical(*(src.Medical[i])));
        }

        deploy_resources(); //place the food inside the map..
    }

    ~Grid() {
        for (int i = 0; i < size; ++i)
            delete[] grid[i];
        delete[] grid;
        for (int i = 0; i < noofsupplies; ++i) {
            delete food[i];
            delete water[i];
            delete mine[i];
            delete medical[i];
        }
    }

    Grid& operator=(Grid rhs) {
        swap(*this, rhs);
        return *this;
    }
};

Which can be greatly simplified by getting rid of all the new and delete calls, let the compiler and STL handle all of the memory allocations and releases for you:

class Grid {
private:
    vector<vector<char> > grid;
    vector<Food> food;
    vector<Water> water;
    vector<Mine> mine;
    vector<Medical> medical;
public:
    Grid(int sizeofgrid) {
        grid.resize(sizeofgrid);
        for (int i = 0; i < sizeofgrid; ++i)
            grid[i].assign(sizeofgrid, '-');

        int noofsupplies = 3 * ((sizeofgrid * sizeofgrid) / 25);
        food.resize(noofsupplies);
        water.resize(noofsupplies);
        mine.resize(noofsupplies);
        medical.resize(noofsupplies);

        deploy_resources(); //place the food inside the map..
    }
};
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • "you are trying to push a `Resource*` instead." - he pushed `*f`, so `Resource` – M.M May 26 '16 at 22:14