Struggling With OOP and Vectors

Pages: 12
Hi,

I currently know a bit of C, and i thought as I am off work on furlough I will learn some C++. I have created a basic airline booking system that outputs to a console window.

So the main menu accepts a passengers details (Name, Age and Sex) and assigns these details to a seat on the plane. The program consists of 'main', the 'plane' class and the 'passengers' class. I have created vectors for both the passenger and also the seats.

So my next step is trying to get the 'passenger' vector to point to the 'seats' vector. Due to both of these vectors being public (global) is it better to do this pointer math in 'main' or in the 'Plane' classes. What is the correct OOP way?

If someone could give me a bit of direction on how to move forward on pointing the passenger vector to a seat vector.

Many thanks,

Rocketman46

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

using namespace std;

//***************************** Passanger Class ******************************************
class Passanger
{
public:
	void Name();
	void Age();
	void Sex();

	vector<string> passanger;
	
private:

};

void Passanger::Name()
{
	string name;
	cout << "Enter name: \n";
	cin >> name;
	passanger.push_back(name);

}

void Passanger::Age()
{
	string age;
	cout << "Enter age: \n";
	cin >> age;
	passanger.push_back(age);
}

void Passanger::Sex()
{
	string sex;
	cout << "Enter sex: \n";
	cin >> sex;
	passanger.push_back(sex);
}

//***************************** Plane Class ******************************************
class Plane
{
public:
	Plane();
	void AvailableSeats();
	void BookSeat();
	void CancelSeat();
	void EmptySeats();

	vector<string> seats;

private:
	
};

Plane::Plane()
{
	// basic seat layout

	seats.push_back("A1"); // 0
	seats.push_back("B1"); // 1
	seats.push_back("C1"); // 2
	seats.push_back("D1"); // 3
	seats.push_back("E1"); // 4
	
}

void Plane::AvailableSeats()
{
	vector<string>::const_iterator iter;

	for (iter = seats.begin(); iter != seats.end(); ++iter)
	{
		cout << *iter;
		cout << "\t";
	}
	cout << endl;
}

void Plane::BookSeat()
{
	string choice;
	//Ptr_passanger = &passanger;

	cout << "Book Seat: \n";
	cout << "Available seats please select one: \n\n";
	AvailableSeats();
	cout << "Select seat: \n";
	cin >> choice; // B1 will be selected for example reasons

	// seats[1] = *Ptr_passanger; // trying to point passanger details to seat loation 1 (B1)

}

void Plane::CancelSeat()
{

}

void Plane::EmptySeats()
{

}

//***************************** Main ******************************************
int main()
{
	Plane plane;
	Passanger passanger1;

	cout << "Welcome to Airline Booking\n\n";
	cout << "Please select from the following choices: \n\n";

	int choice;
	
	do
	{
		cout << "\n\n";
		cout << "1) View available seats: \n";
		cout << "2) Make a booking: \n";
		cout << "3) exit: \n\n";
		cin >> choice;

		switch(choice)
		{
			case 1:
			{
				plane.AvailableSeats();
				break;
			}

			case 2:
			{
				cout << "Please select a seat: \n\n";
				passanger1.Name();
				passanger1.Age();
				passanger1.Sex();
				plane.BookSeat();
				break;
			}

			case 3:
			{
				cout << "exit.\n\n";
				break;
			}

			default:
			{
				cout << "Sorry try again. \n\n ";
				break;
			}

		}

	} while (choice != 3);

    return 0;
}
So my next step is trying to get the 'passenger' vector to point to the 'seats' vector.

What exactly do you mean by that?

What is the correct OOP way?

Usually, it's "more correct" to do anything that specifically involves the sub-elements of an object within functions inside of the class and keep it as far away from main as possible.

For example, your vectors are public, when they can be private. Any work you do to those vectors should be within the class itself or friend functions created for the class. It's safer than having them accessible to any code that wants to change it in main.
I would add a struct of seat with the members ID and empty.
The Plane would have a collection of seats.
The passenger should have a field for the seat id
The actual booking and cancellation could be done in a class Airline which also stores the passengers..
I also would do all the input and output in main and pass the collected data to the Plane and Passenger class.

I hope this makes some sense. English isn't my native language and sometimes I express my clearly enough.
Hi,

Thanks for answering so quickly.

"So my next step is trying to get the 'passenger' vector to point to the 'seats' vector"

Is what i am trying to do and work up to, on the main menu, a passengers details will be taken and stored into a vector 'passenger'. Then next step the passenger has an option to sit in a number of available seats stored in the vector 'seats'. Below is my example:

vector passenger1 // fred

vector passanger2 // harry

vector seats {A1, B1, C1, D1, E1} // empty plane

vector seats {A1, fred, C1, harry, E1} // plane with 2 passengers

I am guessing the passenger vectors would need to point to the seats vector using pointers, but i cannot quite workout how to do this. I am sure i am making this harder than it is but i just cannot see it.

Thanks,

RocketMan46

Hello RocketMan,

your program design looks somewhat weird ;-)

For me, a proper design is as following:

1) A plane has a fixed set of seats,
2) A seat is empty or is reserved by a person.

So we have these three classes: Person, Seat, and Plane. And these classes should be nested.

A rough frame for your code could be:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class Person
{
public:
    // ...add your methods here!
    
private:
    string m_name;
    int m_age;
    char m_sex;
};

class Seat
{
public:
    // ...add your methods here!
    
private:
    bool m_isReseved;
    string m_number;
    Person m_person;
};

class Plane
{
public:
    // Initialize m_seats, add further methods!
    
private:
    vector<Seat> m_seats;
};


int main()
{
    // ...

    switch(choice)
    {
        // ...
        
        case 2:
            Person passenger;
            passenger.ReadData();
            plane.BookSeat( passenger );
            break;
        
        // ...
    }
    // ...
}


*edit: typo
Last edited on
Hi,

Thanks for putting me on the right track. That does make more sense now. I will try again with your layout.

I am stuck in C mode and its hard to think differently ;-)

Many thanks,

RocketMan46
If you want (or need), feel free to post the resulting code here, so we could make further improvement suggestions to it :-)
Hi,

I have used your program layout shell and i have added my code into it. I have run into another OOP problem i do not really understand the flow of OOP. Below are the steps that work so far:

1) passenger details are added into the main menu - working

2) passenger details are returned from 'Person' class back to main using a vector - working

3) At this point i want to add this details into the seat class, but the data members are different. I also notice that in the 'Seat' class, one of the data members m_person is of type 'Person'. How would i use this?

I am guessing the flow of the program is as follows... passenger data is added into the 'Person' class and passed back to main. This data is then passed to the 'Seat' class and passed back to main. Then this data is passed to the 'Plane' class?

Thanks in advance for any help.

Below is my initial program layout:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

using namespace std;

// ********************* Person Class *************************
class Person
{
public:
	void Name();
	void Age();
	void Sex();
	vector<string> ReadData();

private:
	string m_name;
	string m_age;
	string m_sex;
	vector<string> person;
};

void Person::Name()
{
	cout << "Enter name: \n";
	cin >> m_name;

}

void Person::Age()
{
	cout << "Enter age: \n";
	cin >> m_age;
}

void Person::Sex()
{
	cout << "Enter sex: \n";
	cin >> m_sex;
}

vector<string> Person::ReadData()
{
	person.push_back(m_name);
	person.push_back(m_age);
	person.push_back(m_sex);

	return person;
}

// ********************* Seat Class *************************
class Seat
{
public:
	void SeatReserved();
	void SeatNumber();

private:
	bool m_isReseved;
	string m_number;
	Person m_person;
};

void Seat::SeatReserved()
{
	
}

void Seat::SeatNumber()
{

}

// ********************* Plane Class *************************
class Plane
{
public:
	void AvailableSeats();
	void BookSeat(vector<string> PassengerData);
	void CancelSeat();

private:
	vector<string> m_seat;
};

void Plane::AvailableSeats()
{
	// basic seat layout
	m_seat.push_back("A1"); // 0
	m_seat.push_back("B1"); // 1
	m_seat.push_back("C1"); // 2
	m_seat.push_back("D1"); // 3
	m_seat.push_back("E1"); // 4

	vector<string>::const_iterator iter;

	for (iter = m_seat.begin(); iter != m_seat.end(); ++iter)
	{
		cout << *iter;
		cout << "\t";
	}
	cout << endl;
}

void Plane::BookSeat(vector<string> PassengerData)
{
	
	cout << "Please select a seat: \n\n";
	AvailableSeats();

	string choice;
	cin >> choice;	

	// just confirming i can overwrite m_seat location
	if (choice == "A1")
	{
		m_seat.insert(m_seat.begin(), "A2");
	}

}

void Plane::CancelSeat()
{

}

// ********************* Main ********************************
int main()
{
	Plane plane;
	Person passenger;

	cout << "Welcome to Airline Booking\n\n";
	cout << "Please select from the following choices: \n\n";

	int choice;

	do
	{
		cout << "\n\n";
		cout << "1) View available seats: \n";
		cout << "2) Make a booking: \n";
		cout << "3) exit: \n\n";
		cin >> choice;

		switch (choice)
		{
			case 1:
			{
				plane.AvailableSeats();
				break;
			}

			case 2:
			{
				// enter passanger details
				passenger.Name();
				passenger.Age();
				passenger.Sex();

				// return passenger details back to main
				vector<string> PassengerData;
				PassengerData = passenger.ReadData();
				plane.BookSeat(PassengerData);

				// assign customer details to a seat

				// add seat to plane

				break;
			}

			case 3:
			{
				cout << "exit.\n\n";
				break;
			}

			default:
			{
				cout << "Sorry try again. \n\n ";
				break;
			}
		}

	} while (choice != 3);

    return 0;

}
Why does a person have a vector of strings called person?? What is in that vector that isn't in the member data?

What if a seat is reserved but the name is blank? Or vice versa? I'd remove the m_isReserved member and replace it with bool isReserved() { return m_person.size(); } In other words, a seat is reserved if the person has a name.

Plane::m_seat should be called m_seats because there are many of them. It should be a vector of Seat, not a vector of string.

Populate m_seats in Plane's constructor, not AvailableSeats(). Otherwise every time you call AvailableSeats, you'll add new seats to the plane!

Then add some methods to lookup the seat from a seat number or occupant name.

Here is the data that I used in a working version.
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

using namespace std;

// Forward declarations
class Seat;
class Plane;

// ********************* Person Class *************************
class Person
{
public:
    void Name();
    void Age();
    void Sex();
    friend class Plane;
    friend class Seat;
private:
    string m_name;
    string m_age;
    string m_sex;
};

void
Person::Name()
{
    cout << "Enter name: \n";
    cin >> m_name;

}

void
Person::Age()
{
    cout << "Enter age: \n";
    cin >> m_age;
}

void
Person::Sex()
{
    cout << "Enter sex: \n";
    cin >> m_sex;
}

// ********************* Seat Class *************************
class Seat
{
  public:
    Seat(const string &num) : m_number(num) {}
    bool isReserved() const { return m_person.m_name.size(); }
    void SeatNumber();
    string getNumber() const { return m_number; }
    friend class Plane;

private:
    string m_number;
    Person m_person;		// if the name is empty then the seat is not reserved
};

void
Seat::SeatNumber()
{

}

// ********************* Plane Class *************************
class Plane
{
  public:
    Plane();
    void AvailableSeats();
    void BookSeat(const Person &);
    void CancelSeat(const Person &);

    // Given a seat number, return the corresponding seat in m_seat vector,
    // or nullptr if the number is bad
    Seat *numToSeat(const string &num);
    Seat *personToSeat(const Person &person);
  private:
      vector < Seat > m_seats;	// a plane has seats
};


Thanks dhayden,

It will take me a while to work through it but i will come back to you. There is some new concepts in the code that i will have to go and have a read up on.

thanks again.

Rocketman46
Last edited on
Hi dhayden,

I am working through your code and learning lots. I am currently struggling to initialize the 'Seat' class constructor. I have tried to initialize 'num' to 0 in private (int num = 0) and also in main 'Seat seat(0)' and also 'Seat seat = 0' but the compiler shows the error (no default constructor exists for class 'Seat'. If i remove 'Seat seat' from main i do not get this error. I cannot work out what i am doing wrong?

Thanks,

RocketMan46

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/ ********************* Seat Class *************************
class Seat
{
public:
	Seat(const string &num); 
	bool isReserved() const;
	void SeatNumber();
	string getNumber() const;
	friend class Plane;

private:
	string m_number;
	Person m_person;
	int num = 0;
};


Seat::Seat(const string &num) // constructor
	: m_number(num) 
{}  



bool Seat::isReserved() const 
{ 
	return m_person.m_name.size(); 
}


void Seat::SeatNumber()
{

}


string Seat::getNumber() const 
{ 
	return m_number; 
}

// ********************* Main ********************************
int main()
{
	Plane plane;
	Seat seat(0);
	Person passenger;


	cout << "Welcome to Airline Booking\n\n";
	cout << "Please select from the following choices: \n\n";

	int choice;

	do
	{
		cout << "\n\n";
		cout << "1) View available seats: \n";
		cout << "2) Make a booking: \n";
		cout << "3) exit: \n\n";
		cin >> choice;

		switch (choice)
		{
		case 1:
		{
			plane.AvailableSeats();
			break;
		}

		case 2:
		{
			// enter passanger details
			passenger.Name();
			passenger.Age();
			passenger.Sex();		
			break;
		}

		case 3:
		{
			cout << "exit.\n\n";
			break;
		}

		default:
		{
			cout << "Sorry try again. \n\n ";
			break;
		}
		}

	} while (choice != 3);

	return 0;

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Seat
{
public:
	Seat(const string &num); 
	bool isReserved() const;
	void SeatNumber();
	string getNumber() const;
	friend class Plane;

private:
	string m_number;
	Person m_person;
	int num = 0;
};

The Seat ctor expects a string. Why do you pass an int to it?
Your naming is confusing. In the ctor num ist string, in the class num is an int.
Hi,

My mistake i have tried string also but i forgot to change back to string:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Seat
{
public:
	Seat(const string &num); 
	bool isReserved() const;
	void SeatNumber();
	string getNumber() const;
	friend class Plane;

private:
	string m_number;
	Person m_person;
	string num;
};



With string added, the two errors:

1) no default constructor exists for class 'Seat'

2) 'Seat': no appropriate default constructor available
You need to create a seat with a string like this: Seat seat("A1");
Thanks,

I tried every combination other than that.

Many thanks another lesson learnt :-)
Hi,

Another syntax question, that i cannot seem to find an example of. I can print a vector of strings to see the available seats:

Thanks,

1
2
3
4
5
6
7
8
9
10
vector<string> m_seats;

vector<string>::const_iterator iter;

for (iter = m_seats.begin(); iter != m_seats.end(); ++iter)
{
	cout << *iter;
	cout << "\t";
}
cout << endl;


but i cannot seem to print out a vector of vectors:

1
2
3
4
5
6
7
8
9
10
vector<Seat> m_seats;

vector<Seat>::const_iterator iter;

for (iter = m_seats.begin(); iter != m_seats.end(); ++iter)
{
	cout << *iter;
	cout << "\t";
}
cout << endl;


Also

1
2
3
4
5
6
7
8
9
10
vector<Seat> m_seats;

vector<vector<m_seat>>::const_iterator iter;

for (iter = m_seat.begin(); iter != m_seat.end(); ++iter)
{
	cout << *iter;
	cout << "\t";
}
cout << endl;


And lastly

1
2
3
4
5
6
7
8
9
10
vector<Seat> m_seats;

vector<vector<Seat>>::const_iterator iter;

for (iter = Seat.begin(); iter != Seat.end(); ++iter)
{
	cout << *iter;
	cout << "\t";
}
cout << endl;



Here are the most common modern ways to print a vector:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>

using namespace std;

int main()
{
  // modern ways to print a vector
  vector<string> names = {"Anna", "Lisa", "Cassandra"};
  
  // option 1
  for (const auto& name: names)
    cout << name << ' ';
    
  // option 2
  copy(names.begin(), names.end(), ostream_iterator<string>(cout, " "));
}
To print nested vectors:
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
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>

using namespace std;


int main()
{
  // modern ways to print a vector
  vector<string> names = {"Anna", "Lisa", "Cassandra"};
  vector<string> names2 = {"Anja", "Katharina", "Simone"};
  
  vector<vector<string>> combined;
  combined.push_back(names);
  combined.push_back(names2);
  
  for (const auto&  names : combined) // for each vector in combined
  {
    for (const auto& name: names)
        cout << name << ' ';
        
    cout << '\n';
  }
  
}


If you are serious about C++ get a copy of "C++ Standard Library"(2.ed.) by Nicolai Josuttis
Might be around as a .pdf
Hi,

Thanks for your help. Yes i am keen, but struggling lots as new to C++.

I think my made up example of a booking system has been a bit more challenging than i first expected. I make good progress then get caught up in syntax problems and brick wall for a day or so.

Thanks again for your help.

thanks,
It seems you try to learn C++ and OOP at once, which seems too much
Why not postpone your current project and learn of C++ first?
Another useful book is the "C++ Programming Language 4.ed." of Bjarne Stroupstrup. Might also be available as .pdf
Once you have read these 2 books you have a proper understanding of C++.
Pages: 12