Vectors in classes

How do i use vector in classes, cause when i do the following it dont work:



1
2
3
CStart::CStart(int pSpieler){
vector <string> mPlayers(pSpieler); // like this
vector <int> mPenalties(pSpieler);


i cant use the vectors in e.g. :
1
2
3
4
5
6
7
void CStart::get()
{
 for(int i = 0; i < pSpieler; i++)
{
  cout << mMitspieler.at(i) << endl; // gives error, cant find it
}
}
Last edited on
You need to tell us what "doesn't work" means. Be specific.

If the error is that it "cant find it", I assume that means you don't have #include <vector> in your code.

If that isn't the issue, you need to be more specific as to what the problem is, post actual error messages, and probably show more code.

Edit: Question was also asked in this thread: http://www.cplusplus.com/forum/general/271745/
Last edited on
yeah thats my post, i thought its more of a beginner problem so i put it here but thx for giving the link
There's a reference on this site, but it's a little ambiguous. However, there's a really good one here: https://en.cppreference.com/w/cpp/container/vector/vector

To initialise a std::vector with a size, the type should be size_t, not int. So you should be able to say:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <vector>
#include <iostream>
#include <exception>

std::vector<int> create_vector(size_t size) {
    std::vector<int> v(size);
    for (size_t i = 0; i != size; ++i)
        v[i] = i*i;
    return v;
}

int main() {
    auto v = create_vector(8);
    std::cout << v[1] << std::endl;

    try {
        // known to be out of range
        std::cout << v.at(v.size()) << std::endl;
    }
    catch (const std::exception& e) {
        std::clog << "fatal: " << e.what() << std::endl;
    }
}
The shown code fragments look similar to:
1
2
3
4
5
6
7
8
9
void functionA()
{
  int answer = 42;
}

void functionB()
{
  std::cout << answer; // error: unknown identifier 'answer'
}

The point is that variable declared in scope of one function does not exist in other functions.

However, class has members:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class X {
  int answer = -1;
public:
  X() {
    int answer = 42; // this is not X::answer
  }

  void functionB() {
    std::cout << answer;
  }
};

int main() {
  X x;
  x.functionB(); // prints -1
}

Local variable in the body of constructor masks the member X::answer.
Last edited on
@ kbw (8909), i have never seen a vector written in that manner but correct me if i am wrong. I usually write my vector in the following manner below
1
2
3
4
5
6
7
8
9
10
11
12
13
//Declaration of the directive for a vector
#include <vector>

//the vector syntax is as follows --> vector<type> variable_name (total_number_of_elements);

//Hence, we have
vector<int>v(8); // Declares a vector of 8 integers
//size_type represent position and sizes, to loop through a vector, we have
for (vector<double>::size_type i = 0; i < 20; i++)
{

    v[i] = i*i;
}
Last edited on
You have magic constants and due to them a clear error:
1
2
3
4
5
vector<int>v( 8 );
for (vector<double>::size_type i = 0; i < 20; i++)
{
    v[i] = i*i; // The i in [8,20) create out of range errors
}

Vector knows its size. Use that:
1
2
3
4
5
vector<int>v( 8 );
for (vector<double>::size_type i = 0; i < v.size(); i++)
{
    v[i] = i*i;
}

The shown code fragments look similar to:
1
2
3
4
5
6
7
8
9
void functionA()
{
  int answer = 42;
}

void functionB()
{
  std::cout << answer; // error: unknown identifier 'answer'
}



The point is that variable declared in scope of one function does not exist in other functions.


yeah, but how i initalize a vector in a class when i know the ammount of players first in the constructor?
Why is it so hard to actually tell us what the exact error message is, and show the code that produces said error mesage?

but how i initalize a vector in a class when i know the ammount of players first in the constructor?
You mean initializing a vector that is a class member variable?

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

class Foo {
  public:
    Foo(int size)
    : vec(size) // initialized vec
    {
        for (int i = 0; i < size; i++)
        {
            vec[i] = i * 42; // assigns a number to each element
        }
    }
    
    std::vector<int> vec;
};

int main()
{
    Foo foo(20);
}
Last edited on
@olychichi i have never seen a vector written in that manner but correct me if i am wrong.

You are not wrong, and the code actually run is the same in this case. And in small programs, that's fine.

In larger programs, it's often convenient to separate the construction/deletion of objects from their actual use. Why?
* It may not be trivial to construct the object
* Some computation, or additional input may be required
* There are other special circumstances around the construction of particular objects that need it to be refactored out

It happens often enough for this to be so common that there are a number of design patterns that express this principle, see: https://en.wikipedia.org/wiki/Creational_pattern

Anyway, I've used that pattern above.
1
2
3
4
5
    Foo(int size)
    : vec(size)
    {
        // code
    }

A name for that syntax is member initializer list.
See https://www.learncpp.com/cpp-tutorial/8-5a-constructor-member-initializer-lists/
main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "maexle.h"





int main()
{
	int numberOfPlayers;
	do {
		cout << "Number of Players: ";
		cin >> numberOfPlayers;
	} while  (numberOfPlayers < 3);

	CStart myStart(numberOfPlayers);

	myStart.get();


	system("pause");
	return 0;
}

maexle.cpp:
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 "maexle.h"


CStart::CStart()
{}
CStart::~CStart()
{}

CStart::CStart(int pPlayer)
{
	vector <string> mPlayers(pPlayer);
	vector <int> penalties(pPlayer);

	for (int i = 0; i < pPlayer; i++) {
		cout << "Player " << i+1 << ": ";
		cin >> mPlayers.at(i); //Error  code 2 appears here, when 1 and 2 are deletet
	}
}

void CStart::get()
{
	for (int i = 0; i < 5; i++) {
		cout << mPlayers.at(i) << endl;  //Error1 appears here
	}
}

maexle.h:
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
#pragma once
#include <string>
#include <vector>
#include <iostream>
using namespace std;

class CVector
{
public:
	vector <string> mPlayers; //1
	vector <int> penalties; //2
};

class CStart:public CVector
{
public:
	CStart();
	CStart(int pSpieler);
	~CStart();

	void get();
private:
		
};


Error Code1:
Unbehandelte Ausnahme bei 0x760E4402 in testvectors.exe: Microsoft C++-Ausnahme: std::out_of_range bei Speicherort 0x003EF318.

Error Code2:
Unbehandelte Ausnahme bei 0x760E4402 in testvectors.exe: Microsoft C++-Ausnahme: std::out_of_range bei Speicherort 0x00D5F8B0.

How can i make, that the vector is "usable" for other functions of CStart like get()?

Last edited on
Ah, so that's a run-time error at least (as opposed to compiler error).

In line 10 of maexle.h, you define a member variable, mPlayers.
In line 11 of maexle.cpp, you declare a local variable, mPlayers.

This local variable shadows the member variable, hiding the member variable.

To make things more complicated, you have a class inheritance hierarchy, albeit a simple one.

Do something similar to what I showed in my previous post,
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

class CVector
{
public:
	CVector(int pSpieler); // define this!
	vector <string> mPlayers;
	vector <int> penalties;
};

 // ...

CVector::CVector(int pPlayer)
: mPlayers(pPlayers),
  penalties(0) // assume we start with 0 penalties, change if necessary
{

}
 
// ...

CStart::CStart(int pPlayer)
: CVector(pPlayer) // calls the base-class constructor
{
	for (int i = 0; i < pPlayer; i++) {
		cout << "Player " << i+1 << ": ";
		cin >> mPlayers.at(i);
	}
}


PS: In English, past tense usually follows the pattern of becoming "-ed", never "-et", e.g. "delete" --> "deleted".
I just say this because I know it's a common mistake German-speakers make.
Last edited on
1
2
3
4
5
6
void CStart::get()
{
	for (int i = 0; i < 5; i++) {
		cout << mPlayers.at(i) << endl;
	}
}

How do you know that every CStart has exactly 5 players?
You can't know that.

The mPlayers does know how many elements it has. Use that information:
1
2
3
4
5
6
void CStart::get()
{
	for ( int i = 0; i < mPlayers.size(); i++) {
		cout << mPlayers.at(i) << endl;
	}
}

or, with range for syntax:
1
2
3
4
5
6
void CStart::get()
{
	for ( auto player : mPlayers ) {
		cout << player << endl;
	}
}

With these the CStart::get() will not crash the program.
Hello,
thx for your answers! I think i have it now - at least its working :)

main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "maexle.h"

int main()
{
	int numberOfPlayers;
	do {
		cout << "Number of Players: ";
		cin >> numberOfPlayers;
	} while  (numberOfPlayers < 3);

	CStart myStart(numberOfPlayers);

	myStart.get();


	system("pause");
	return 0;
}


maexle.cpp:
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
31
32
#include "maexle.h"

CStart::CStart()
{}
CStart::~CStart()
{}

/*
CVector::CVector()
{}
CVector::~CVector()
{}
CVector::CVector(int pPlayers) :mPlayers(pPlayers), penalties(0)
{}
*/

CStart::CStart(int pPlayer):mPlayers(pPlayer),penalties(0)
{
	

	for (int i = 0; i < pPlayer; i++) {
		cout << "Player " << i+1 << ": ";
		cin >> mPlayers.at(i);
	}
}

void CStart::get()
{
	for (int i = 0; i < mPlayers.size(); i++) {
		cout << mPlayers.at(i) << endl;
	}
}


maexle.h:
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
#pragma once
#include <string>
#include <vector>
#include <iostream>
using namespace std;
/*
class CVector
{
public:
	CVector();
	CVector(int pSpieler);
	~CVector();
	vector <string> mPlayers;
	vector <int> penalties;
};
*/
class CStart//:CVector
{
public:
	CStart();
	CStart(int pSpieler);
	~CStart();
	vector<string> mPlayers;
	vector<int> penalties;
	void get();
private:
		
};


I dont think i need an extra class CVector, it just make things more complicated like u said.
Just for interesst, if i add another class, in which i need the vectors. Will i just have to give this class CStart like this:?
1
2
3
4
class CAnyClass:CStart
{
//...
};
Last edited on
Yes, if you want to inherit CStart, that's how you would do that. Normally people would want public inheritance, (class CAnyClass : public CStart), but in this case it doesn't really make a difference since it's all public. (See: https://stackoverflow.com/a/1374362)

But if you're asking about design, well it's hard to say what would be a good design in this case, because I don't know what the actual purpose of these classes are. I don't understand the significant of class names like "Vector" or "Start". What do any of those words have to do with players, or penalties? Perhaps a "Game" class would be a better name; I'm not sure.

- Usually, you can think of inheritance as an "is-a" relationships. Is CStart a more specific type of of CVector? Is a CAnyClass a more specific type of CVector? I can't answer that, only you can.
- The other way of building up classes is through aggregation, which is to say, a "has-a" relationship. e.g. perhaps a Game has-a vector of Players. In my opinion, huge inheritance structures tend to become convoluted, but a few layers of inheritance is OK.
Last edited on
Like in the above:
1
2
3
4
5
6
7
class CStart
{
  // ...
  vector<string> mPlayers;
  vector<int> penalties;
  // ...
};

Object of type CStart has-a collection "mPlayers"
Object of type CStart has-a collection "penalties"

1
2
3
4
class CAnyClass : public CStart
{
  //...
};

Object of type CAnyClass is-a object of type CStart

1
2
3
4
class Other : private CStart
{
  //...
};

Type Other is-implemented-in-terms-of type CStart


class, in which i need the vectors

Does "the vectors" mean some particular instances? For example,
1
2
3
4
5
6
int main() {
  CStart one(42);
  CStart two(7);
  CAnyClass example(3);
  // ...
}

Does the object 'example' need to have vectors of its own, or does it need to access the elements of vectors that object 'one' has?
Topic archived. No new replies allowed.