How to initialize classes to always be usable

Hi everybody,

I am currently trying to figure what to do to initialize all functions at the start so that the order I have created the functions in does not matter.

I have tried making prototype functions but that is really the only solution I could think of.

The problem is on line 35 in the "Balance" class where I am trying to use "Menu menu;" which is the constructor for the Menu class.

Thanks for any help.

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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
  #include <iostream>
#include <string>
#include <exception>

using namespace std;

class Balance
{
private:
	int theChoice = 0;
	double USD = 0, Peso = 0, AUD = 0, Bit = 0, Yen = 0;
	double USF = 0, PF = 0, AUF = 0, BF = 0, YF = 0;
public:

	void choice()
	{
		try
		{
			cout << "What would you like to do?\n1. Add a currency\n2. Check your balance\n3. Exit" << endl;
			cin >> theChoice;
			if (theChoice != 1 && theChoice != 2 && theChoice != 3)
			{
				throw 0;
			}
			else if (theChoice == 1)
			{
				add();
			}
			else if (theChoice == 2)
			{
				view();
			}
			else if (theChoice == 3)
			{
				Menu menu;
			}
		}
		catch (int e)
		{
			if (e == 0)
			{
				cout << "That is not a valid answer. Try again!" << endl;
				choice();
			}
		}
	};

	void view()
	{
		cout << "Total amount of United States Dollar (USD) owned: $" << USF << "\nTotal amount of Mexican Pesos owned: " << PF << "\nTotal amount of Australian Dollar owned: $" << AUF << "\nTotal Bitcoin owned: " << BF << "\nTotal Amount of Japanese Yen owned: " << YF << endl;
		choice();
	}

	void add()
	{
		try
		{
			cout << "What currency would you like to add?\n1. United States Dollar (USD)\n2. Mexican Pesos\n3. Australian Dollar (AUD)\n4. Bitcoin\n5. Japanese Yen" << endl;
			cin >> theChoice;
			if (theChoice < 1 || theChoice > 5)
			{
				throw 0;
			}
			switch (theChoice)
			{
			case 1:
				addUSD();
				TotalUS();
				choice();
				break;
			case 2:
				addPesos();
				TotalPesos();
				choice();
				break;
			case 3:
				addAUD();
				TotalAUD();
				choice();
				break;
			case 4:
				addBitcoin();
				TotalBitcoin();
				choice();
				break;
			case 5:
				addYen();
				TotalYen();
				choice();
				break;
			}
		}
		catch (int e)
		{
			if (e == 0)
			{
				cout << "That is not a valid answer. Try again!" << endl;
				add();
			}
		}
	}

	double addUSD()
	{
		try
		{
			cout << "How much USD would you like to add: ";
			cin >> USD;
			if (USD < 0.01)
			{
				throw 0;
			}
		}
		catch (int e)
		{
			if (e == 0)
			{
				cout << "Amount must be at least $0.01" << endl;
				addUSD();
			}
		}
		return USD;
	}
	double addPesos()
	{
		try
		{
			cout << "How many pesos would you like to add: ";
			cin >> Peso;
			if (Peso < 1)
			{
				throw 0;
			}
		}
		catch (int e)
		{
			if (e == 0)
			{
				cout << "Amount must be at least 1" << endl;
				addUSD();
			}
		}
		return Peso;
	}
	double addAUD()
	{
		try
		{
			cout << "How many AUD would you like to add: ";
			cin >> AUD;
			if (AUD < 0.01)
			{
				throw 0;
			}
		}
		catch (int e)
		{
			if (e == 0)
			{
				cout << "Amount must be at least $0.01" << endl;
				addUSD();
			}
			
		}
		return AUD;
	}
	double addBitcoin()
	{
		try
		{
			cout << "How many bitcoin would you like to add: ";
			cin >> Bit;
			if (Bit < 0.01)
			{
				throw 0;
			}
		}
		catch (int e)
		{
			if (e == 0)
			{
				cout << "Amount must be at least 0.01" << endl;
				addUSD();
			}
		}
		return Bit;
	}
	double addYen()
	{
		try
		{
			cout << "How many Yen would you like to add: ";
			cin >> Yen;
			if (Yen < 1)
			{
				throw 0;
			}
		}
		catch (int e)
		{
			if (e == 0)
			{
				cout << "Amount must be at least 1" << endl;
				addUSD();
			}
		}
		return Yen;
	}

	double TotalUS()
	{
		USF += USD;
		cout << "Total amount in United States Dollar is $" << USF << endl;
		return USF;
	}
	double TotalPesos()
	{
		PF += Peso;
		cout << "Total amount in Pesos is " << PF << endl;
		return PF;
	}
	double TotalAUD()
	{
		AUF += AUD;
		cout << "Total amount in Australian Dollars is $" << AUF << endl;
		return AUF;
	}
	double TotalBitcoin()
	{
		BF += Bit;
		cout << "Total amount in BitCoin is " << BF << endl;
		return BF;
	}
	double TotalYen()
	{
		YF += Yen;
		cout << "Total amount in Japanese Yen is " << YF << endl;
		return YF;
	}
	Balance()
	{
		choice();
	}
};

class Convert
{
private:
	double amt = 0, USD = 0;
	int theChoice;
public:

	void choice()
	{
		try
		{
			cout << "What currency would you like to convert to United States Dollar (USD)?\n1. Mexcian Pesos\n2. Austraian Dollars\n3. Bitcoin\n4. Japnese Yen";
			cin >> theChoice;
			if (theChoice < 1 || theChoice > 4)
			{
				throw 0;
			}
			switch (theChoice)
			{
			case 1:
				P2U();
				choice();
				break;
			case 2:
				A2U();
				choice();
				break;
			case 3:
				B2U();
				choice();
				break;
			case 4:
				Y2U();
				choice();
				break;
			}
		}
		catch (int e)
		{
			if (e == 0)
			{
				cout << "That is not a valid answer. Try again!" << endl;
				choice();
			}
		}
	}

	void P2U()
	{
		cout << "How many Mexican Pesos? ";
		cin >> amt;
		USD = amt * 0.047;
		cout << amt << " Mexian Pesos is $" << USD << " USD." << endl;
	}
	void A2U()
	{
		cout << "How many Australian Dollars? ";
		cin >> amt;
		USD = amt * 0.71;
		cout << amt << " Australian Dollars is $" << USD << " USD." << endl;
	}
	void B2U()
	{
		cout << "How many Bitcoin? ";
		cin >> amt;
		USD = amt * 48162.70;
		cout << amt << " Bitcoin is $" << USD << " USD." << endl;
	}
	void Y2U()
	{
		cout << "How many Japanese Yen? ";
		cin >> amt;
		USD = amt * 0.0088;
		cout << amt << " Japnese Yen is $" << USD << " USD." << endl;
	}


	Convert()
	{
		choice();
	}
};

class Menu
{
private:
	int theChoice;
public:
	void choice()
	{
		try
		{
			cout << "What would you like to go to?\n1. Balance\n2. Convert\n3. Exit" << endl;
			cin >> theChoice;
			if (theChoice < 1 || theChoice > 3)
			{
				throw 0;
			}
			else if (theChoice == 1)
			{
				Balance balance;
			}
			else if (theChoice == 1)
			{
				Convert convert;
			}
			else if (theChoice == 1)
			{
				exit(EXIT_FAILURE);
			}
		}
		catch (int e)
		{
			if (e == 0)
			{
				cout << "That is not a valid answer. Try again!" << endl;
				choice();
			}
		}
	}

	Menu()
	{
		choice();
	}
};

int main()
{
	Menu menu;

	return 0;
}
The problem is on line 35 in the "Balance" class where I am trying to use "Menu menu;" which is the constructor for the Menu class.
1
2
3
4
else if (theChoice == 3)
{
    Menu menu;
}

Here you create a new "local" Menu object with "automatic" storage duration, but it will be destroyed immediately after construction, because your variable menu obviously goes out of scope right away!

https://linuxhint.com/object-lifetime-and-storage-duration-in-cpp/#3

If you want the Menu object to live as long as the enclosing Balance object, then you have to make menu a member variable of the Balance class, not a local variable in the choice() method.

Example:
1
2
3
4
5
6
7
8
9
class Balance
{
private:
	int theChoice = 0;
	double USD = 0, Peso = 0, AUD = 0, Bit = 0, Yen = 0;
	double USF = 0, PF = 0, AUF = 0, BF = 0, YF = 0;
        Menu menu; // <-- !!!

/* ... */
Last edited on
Okay, the "Menu menu;" is now a variable of the Balance class. However it is still showing an error stating "'menu': unknown override specifier"
1
2
3
4
	int theChoice = 0;
	double USD = 0, Peso = 0, AUD = 0, Bit = 0, Yen = 0;
	double USF = 0, PF = 0, AUF = 0, BF = 0, YF = 0;
	Menu menu;

Last edited on
How would I go about running that then if the user chooses to? (chooses choice 3)

What about something like:
1
2
3
4
else if (theChoice == 3)
{
    menu.doSomething();
}


...assuming that the Menu class has a method doSomething() which you want to call when the user has chosen 3. Or maybe add a more general method to Menu that takes the choice value as argument:

1
2
3
4
else if (theChoice == 3)
{
    menu.setChoice(3);
}
Last edited on
Sorry about the response edit while you were responding.
Code like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
double addUSD()
	{
		try
		{
			cout << "How much USD would you like to add: ";
			cin >> USD;
			if (USD < 0.01)
			{
				throw 0;
			}
		}
		catch (int e)
		{
			if (e == 0)
			{
				cout << "Amount must be at least $0.01" << endl;
				addUSD();
			}
		}
		return USD;
	}


is not really good practice as you are using exceptions for normal input validation. Usually you would do this in a loop like this:

1
2
3
4
5
6
7
8
9
double addUSD() {
	double USD{};

	do {
		cout << "How much USD would you like to add (> 0.01): ";
		cin >> USD;
	} while ((USD < 0.01) && (cout << "Amount must be at least $0.01\n"));
	return USD;
}


and similar for other functions.

Exceptions are meant to be used for truly exceptional run-time errors and not for just usual input validation.
Exceptions are meant to be used for truly exceptional run-time errors and not for just usual input validation.
I imagine the upper end of "truly exceptional" contains things like "CPUStruckByHalleysCometException" and "UniversalHeatDeathException", but what does the lower end look like? In other words if run-time errors can be measured on a scale from "ordinary" to "truly exceptional", what is the most "ordinary" run-time error you can think of that is still "truly exceptional"?

In my opinion the problem with OP's use of exceptions isn't that they are used for "usual input validation" but that they are killing flies with a cannon by using them for local flow control within tiny functions.
Hello C++98!

Default member initialization in a class is very much a "best practice."
https://arne-mertz.de/2015/08/new-c-features-default-initializers-for-member-variables/
Topic archived. No new replies allowed.