help creating a vector of classes

I am learning to use classes and i want to create a vector of classes.
i can create the class and the vector of the class okay, but i cant seem to add to the vector using push_back.

here is what i have tried:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <vector>

class Enemy
{
public:
	int health;
	int damageDealt;

	void takesDamage(int amount)
	{
		health = health - amount;
	}
};


int main()
{
	std::vector<Enemy> bob;
	bob.push_back(100,10);
	std::cout << bob.health[0];
return 0;
}


can anybody explain what i am doing wrong?
thank you
You made a vector of Enemy objects.

So you have to push_back an Enemy object.


1
2
3
	std::vector<Enemy> bob;
        Enemy anEnemy; // create an Enemy object
	bob.push_back(anEnemy); // put it on the end of the vector 

Hello tunplus,

The problem is with line 21.

A vector is similar to an array. So you have to access the vector elements like you would an array.

Your line std::cout << bob.health[0]; right idea, but wrong order. What you want is std::cout << bob[0].health;. "bob" is the vector with elements like an array. "health" is a member variable of the class.

My understanding of classes is the the variables should be "private" so that only the "public" functions of the class can access them. As you have it the whole program can access these variables. To me this defeats the purpose of the class.

Not sure what you intended for line 20, but it does not work.

The default ctor does nothing to initialize your variables or give them any values and there is no overloaded ctor to work with.

Line 20 either needs to push back an object of the class or the class needs an overloaded ctor to handle the numbers.

Hope that helps,

Andy
You defined bob as a std::vector of Enemies. Should the compiler guess by a couple of ints you want to create an Enemy? It’s not human (yet).

Firstly, you need a class constructor, i.e. a method Enemny() in your class.
If you provide an Enemy(int, int), you have two possible solutions:

1) Take advantage of the std::vector::emplace_back() method.
emplace_back() try to build a class instance by the data you provide (more or less):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <vector>


class Enemy {
public:
    int health;
    int damage_dealt;
    
    Enemy(int health_arg, int damage_dealt_arg)
        : health { health_arg }
        , damage_dealt { damage_dealt_arg }
    {
    }

    void takesDamage(int amount)
    {
        health = health - amount;
    }
};


int main()
{
    std::vector<Enemy> bob;
    bob.emplace_back(100, 10);
    std::cout << bob.at(0).health << '\n';
    return 0;
}


2) Otherwise you could create a temporary Enemy object that is copied inside the vector:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <vector>


class Enemy {
public:
    int health;
    int damage_dealt;
    
    Enemy(int health_arg, int damage_dealt_arg)
        : health { health_arg }
        , damage_dealt { damage_dealt_arg }
    {
    }

    void takesDamage(int amount)
    {
        health = health - amount;
    }
};


int main()
{
    std::vector<Enemy> bob;
    bob.push_back( Enemy(100, 10) );
    std::cout << bob.at(0).health << '\n';
    return 0;
}

You are trying to create in-place a class instance. IF you had a constructor, you can do that with emplace_back instead of push_back.

http://www.cplusplus.com/reference/vector/vector/emplace_back/

You need to access the vector element before you can access your class data.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <vector>

class Enemy
{
public:
   int health;
   int damageDealt;

   Enemy(int h, int d) : health(h), damageDealt(d) { }

   void takesDamage(int amount)
   {
      health = health - amount;
   }
};

int main()
{
   std::vector<Enemy> bob;

   bob.emplace_back(100, 10);

   std::cout << bob[0].health << '\n';
}

100
If using more modern C++ you can also just use uniform initialization in a push_back(), with or without the constructor.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <vector>

class Enemy
{
public:
   int health;
   int damageDealt;

   //Enemy(int h, int d) : health(h), damageDealt(d) { }

   void takesDamage(int amount)
   {
      health = health - amount;
   }
};

int main()
{
   std::vector<Enemy> enemies;

   enemies.push_back({100, 10});
   
   std::cout << enemies[0].health << '\n';

   // Or something like?:
   std::vector<Enemy> my_enemies{{100, 10}, {200,20}};
   for(auto& itr : my_enemies)
      std::cout << itr.health << ',' << itr.damageDealt << std::endl;
}
Another reason why I like using as much as possible uniform initialization.
jlb wrote:
with or without the constructor.

As long as the properties are declare public. That doesn’t work if they are private.
This doesn’t compile:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <vector>

class Enemy
{
public:
   //Enemy(int h, int d) : health(h), damageDealt(d) { }

   void takesDamage(int amount)
   {
      health = health - amount;
   }

private:
   int health;
   int damageDealt;
};

int main()
{
   std::vector<Enemy> enemies;

   enemies.push_back({100, 10});
   std::vector<Enemy> my_enemies{{100, 10}, {200,20}};
}


There’s a post where lastchance corrects me on that :-(

As long as the properties are declare public. That doesn’t work if they are private.
This doesn’t compile:

Correct, in this case you need the constructor and even printing the values will require some kind of "public" function.

thank you for the responses everybody <3
furry guy's answer got it to work (although kudos to handy andy, i did also make a mistake on line 21!), but i see from the responses i still have much learning to do.
i am going to read through all the replies carefully and learn to fully understand what is going on. i think i may have jumped ahead of my learning a little and need to slow down :)

thank you everybody
Enoizat brings up a very good point about how to access a vector's elements. operator [] vs. at.

operator[] does no bounds checking, it is very easy to go out of bounds. at does perform bounds checking, and if the program tries to access an element the vector does not own an exception is thrown (the program crashes if you don't try/catch).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <vector>

int main()
{
   std::vector<int> my_vec { 34, 56, -21, 5002, 365 };

   std::cout << "1st element at index 0: " << my_vec[0] << '\n';
   std::cout << "2nd element at index 1: " << my_vec.at(1) << '\n';
   std::cout << "3rd element at index 2: " << my_vec[2] << '\n';
   std::cout << "4th element at index 3: " << my_vec.at(3) << '\n';
   std::cout << "5th element at index 4: " << my_vec[4] << "\n\n";

   // one of the most common errors when dealing with vectors is accessing past the last element

   std::cout << "6th element at index 5: " << my_vec[5] << "\n\n";  // out of bounds!

   // std::cout << my_vec.at(5) << '\n';  // crashes!

   std::cout << "The first element is: " << my_vec.front() << '\n';
   std::cout << "The last element is:  " << my_vec.back() << '\n';
}

1st element at index 0: 34
2nd element at index 1: 56
3rd element at index 2: -21
4th element at index 3: 5002
5th element at index 4: 365

6th element at index 5: 11688672

The first element is: 34
The last element is:  365

Uncomment line 18 and watch the program fall down and go *BOOM!*



thanks for the info.
i have much learning ahead of me!
to be honest im not sure im going about this the best way anyway. but i am learning a lot from doing it wrong :) and from the people here on this forum <3
Topic archived. No new replies allowed.