Help, Object Oriented Programming C++

Pages: 12
Well, just as the title reads I am taking a course in Object Oriented. We are having our last assignment of the course and sadly, this assignment is going to be crazy. Its a 9 file assignment and to make matters worse this is an online class. This assignment will be involving Composition, Inheritance, and Polymorphism. I have read her modules but I still have no idea what the hell is going on. So far I do not have any legit questions but I just want to start this topic off by asking if there is website or link that you guys know of that explains Composition, Inheritance, and Polymorphism perfectly?. P.S: Will continue posting in topic once I run into problems during the assignment.

The reason there are 9 files in my assignment is because there are 4 classes and somehow they are all related. I assume Inheritance has something to do with it.
This site: http://www.learncpp.com/ , chapters 10, 11 and 12.
For every class you need a .cpp and a .h file, so 4 classes = 8 files, and then 1 main.cpp gives you a total of 9 files.
Thank you Fransje been reading those chapters and it cleared about 70% of my confusion.

and Thanks kautzd06, I already had that idea in my head but I had a sense of doubt in my mind that I was probably wrong but now the doubt it gone.


So far, I started the assignment. I set the entire assignment up, I created the files and I also included the member variables/functions/constructors that were given by the professor. Now I am ready to fill up the details but I have run into small details I don't understand in each of the headers/cpp's. Luckily I have this community here. I'll try to specify the issues and I'll post the Headers/Cpp's. To give you guys the overview of the assignment. So there won't be any confusion when I ask for help.

Will be posting soon again
closed account (S6k9GNh0)
kautzd06, this is false. That's not even true in Java.
It's false to say you need a .h and a .cpp for each class, but it's the conventional way to do things (as long as you're not writing a template class). And, if you're learning, I'd say it's the best way to do it until you have the skills and experience to correctly judge when it's right to do it differently.
Thanks for the replies guys. In this case katzd06 is correct. So far, I asked the professor for some help and she stated to begin with the base Account .h/.cpp and the Derived Checkings .h/.cpp.

These are the setups I have so far for account.h/cpp and checking.h/.cpp. I am going to fill up the details in a bit. So here is a list of some of the question I have for these files.

Account.h/cpp QUESTIONS:
1. Do I have the #ifndef #define #endif in the correct places? and did I name them correctly?
2. In account.h class. There is a private variable that is suppose to be named "cust". The word object is throwing me off. What type of variable am I suppose to declare it?.
3. On account.h for the public member functions, I still don't know 100% how to tell which will be virtual, non-virtual or pure virtual or non pure virtual. (I'll reread the chapter once more).
4. Inside account.cpp on the function named "getBalance()". Is it safe to call it a "int" function since its purpose is to "return Balance".
5. One thing that has been bugging me is how do I call a constructor from another subclass to another. I still haven't grasped that idea or know how to do it.
6. On the member function "makeWithdrawal()" should I keep it as a Void function or should I make it to a boolean function?.


Checking.h/cpp QUESTIONS:
1. On both the no arguement constructor "Checking()" and the three arguement constructor. I have no idea what it means to "invoke". The proper english definition is easy but I don't understand in c++ terms.
2. Why does every .cpp/.h have the same type of public member functions. It confuses me so much.


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
Account.h
#ifndef ACCOUNT_H
#define ACCOUNT_H
#include <iostream>
using namespace std;


class Account
{
private:
	float balance;
	//cust which is a Customer object. The word "object" is throwing me off. What type of variable should I make cust?.
public:
	Account()
	{
		balance = 0;
		/*a no-argument constructor which sets balance to zero and calls the corresponding no-argument Customer 
		constructor for default initialization of the Customer member variables to null strings.
		^I can't seem to remember how to call a constructor inside another constructor.*/
	}

	Account(/*two arguement*/)
		{
			/*a two-argument constructor which sets balance to the value of the first parameter, 
			a floating point value entered by the user in the test driver, and sets cust to the value of the second parameter, 
			the Customer variable c created and initialized in the test driver, using the overloaded assignment operator of the 
			Customer class*/
	}
	void makeDeposit(float dep);
	void makeWithdrawal(float with);
	void getBalance(float bal);
	void view();	
	void adjustBalance();

/*You will need to determine which of these functions will be virtual, which will be pure virtual, and which will be 
neither virtual nor pure virtual. You may be better able to determine these after examining the specifications 
for the Savings subclass which follows.*/

};
#endif 



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
Account.cpp
#include "account.h"


void makeDeposit()
{
	/*updates the balance by adding its parameter (a floating point value which represents the amount of a deposit) to the existing balance.  
	The subclasses may access this function but will also have their own makeDeposit member function.  This function has no return value*/
}
void MakeWithdrawal()
{
	/*updates the balance by subtracting its parameter (a floating point value which represents the amount of a withdrawal) 
	from the existing balance. This function returns a boolean value, which is always true for this base class.  
	The subclasses may access this function but will also have their own makeWithdrawal member function, 
	which may return true or false depending on whether the withdrawal is permitted as described below*/
}
void Account::getBalance(float bal)
{
	return bal;
//returns the current account balance
}
void view()
{
	/*calls the Customer’s view function to view the customer information, and then displays the current account balance.  
	The subclasses may access this function but will also have their own view member function.  
	This function has no parameters and no return value.*/
}
void adjustBalance()
{
	//does absolutely nothing in this class; will be overridden in the subclasses.
}



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
Checking.h
#ifndef CHECKING_H
#define CHECKING_H
#include <iostream>



class Checking
{
private:
	bool overdraftProtection;
public:
	Checking()
	{
		//a no-argument constructor which invokes the Account base class no-argument constructor and then sets overdraftProtection to false
	}
	Checking(/*three arguement*/)
	{
		/*a three-argument constructor which invokes the Account base class two-argument constructor and then sets the overdraftProtection 
		to the user-supplied value (which the user supplies via the given test driver).*/
	}

	void makeDeposit();
	bool makeWithdrawal();
	void adjustBalance();	
	void view();




};
#endif 




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
Checking.cpp
#include "checking.h"



void makeDeposit()
{
	// the base class’ makeDeposit function, passing the user supplied deposit amount as a parameter.  This function has no return value
}
bool makeWithdrawal()
{
	/*determines whether a withdrawal can be made, and if so, calls the base Account class’ makeWithdrawal function, 
	passing the user-supplied withdrawal amount as a parameter.  A withdrawal can only be made if (1) making the withdrawal 
	will not result in a negative balance, or (2) the customer has overdraft protection.  
	Returns a boolean true if the withdrawal can be and is made; false otherwise.*/
}
void view()
{
	/*displays the heading “Checking Account” and then calls the base Account class’ view function to display general 
	customer / account information. This function has no parameters and no return value*/
}
void adjustBalance()
{
	/*updates the balance by applying a constant service charge, if any.  
	The service charge (a constant $10) is applied to the balance if the balance falls below the specified minimum 
	(a constant $1,000) after the total deposit and allowed withdrawal amounts are applied. 
	This function has no parameters and no return value.*/
}

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
Test.cpp
#include <iostream>
using namespace std;
#include "account.h"
#include "checking.h"
#include "savings.h"
const int MAX = 4;
void doTransactions (Account*);
 
int main()
{          
            Account* acctsPtr [MAX];
            char acctType;
            bool validType = true;
            char custName[NAME_SIZE];  //Alternative:  string custName;
            char acctID [ID_SIZE];     //Alternative:  string acctID;
            double startBal;
 
            int aNum;
            for (aNum = 0; aNum < MAX && validType; aNum++)
            {
                        cout << "Enter c for checking; s for savings; any other character to quit: ";
                        cin >> acctType;
                        acctType = tolower (acctType);
 
                        if (acctType == 'c' || acctType == 's')
                        {
                                                cout << "Enter customer name: ";
                                                cin >> custName;
                                                cout << "Enter account number: ";
                                                cin >> acctID;
                                                cout << "Enter account beginning balance: ";
                                                cin >> startBal;
 
                        }
 
                        switch (acctType)
                        {
                                    case 'c':
                                    {          
                                                char response;
                                                bool overdraftOk;
                                                cout << "Does this account have overdraft protection? ";
                                                cin >> response;
                                                overdraftOk = (tolower(response) == 'y')? true : false;
                                                Customer c (custName, acctID);
                                                acctsPtr[aNum] = new Checking (c, startBal, overdraftOk);
                                                doTransactions (acctsPtr[aNum]);
                                                acctsPtr[aNum]->adjustBalance();
                                                cout << "Balance after service charge (if any): " <<
                                                              acctsPtr[aNum]->getBalance() << endl;
                                                break;
                                    }
                                   
                                    case 's':
                                    {
                                                double intRate;
                                                cout << "Enter current monthly interest rate: ";
                                                cin >> intRate;
                                                Customer c (custName, acctID);
                                                acctsPtr[aNum] = new Savings (c, startBal, intRate);
                                                doTransactions (acctsPtr[aNum]);
                                                acctsPtr[aNum]->adjustBalance();
                                                cout << "Balance after interest: " <<
                                                              acctsPtr[aNum]->getBalance() << endl;
                                                break;
                                    }
 
                                    default:
                                                validType = false;
                                                aNum--;
                                                break;
                        }
            }
 
            int totalAccts = aNum;
            cout << "\nAccounts:\n";
            for (int i = 0; i < totalAccts; i++)
            {
                        acctsPtr[i]->view();
                        cout << "\n";
            }
 
            for (int i = 0; i < totalAccts; i++)
                        delete acctsPtr[i];
}
 
void doTransactions (Account * aPtr)
{
            double depAmt, withdAmt;
 
            cout << "Enter total deposits: ";
            cin >> depAmt;                    
            aPtr->makeDeposit (depAmt);
            cout << "Balance after deposits: "
                         << aPtr->getBalance() << endl;   
           
            cout << "Enter total withdrawals: ";
            cin >> withdAmt;
            if (aPtr->makeWithdrawal (withdAmt))
                        cout << "Balance after withdrawals: "
                                    << aPtr->getBalance() << endl;
            else
                        cout << "Withdrawal not made -- balance too low\n"
                                     << " and no overdraft protection\n";
}
1. Do I have the #ifndef #define #endif in the correct places? and did I name them correctly?

Yes, you have them in the right place. They're supposed to protect the entire contents of the header file, and that's what you've done.

There's no "right" name and "wrong" name for them, but the important thing is that each header file uses a different symbol from all the other header files. Basing the symbol on the name of the header file is the usual way of doing that, so that you've done is fine.

2. In account.h class. There is a private variable that is suppose to be named "cust". The word object is throwing me off. What type of variable am I suppose to declare it?.

Do you have a Customer class? If not, are you supposed to write one? Because it sounds like what you're supposed to use is an object of that class.

3. On account.h for the public member functions, I still don't know 100% how to tell which will be virtual, non-virtual or pure virtual or non pure virtual. (I'll reread the chapter once more).

A textbook or tutorial will explain this properly, but in a nutshell:

- Use a virtual method if you want to be able to call the method on a base class pointer, and automatically know that it should really be calling the method on the derived class that the pointer actually points to.

- Use a non-virtual method if you want to be able to call the method on a base class pointer, and not call the method on the derived class, i.e. call the base-class version of the method instead, regardless of what the pointer actually points to.

- Use a pure virtual method when you're defining an interface, i.e. when you're saying that the class has no definition for that method, but a derived class must define its own version of that method.

4. Inside account.cpp on the function named "getBalance()". Is it safe to call it a "int" function since its purpose is to "return Balance".

You define the return type to say what type of data is being returned. If you're returning the balance, then that's a float, so the return type of getBalance() should be float, not int.

5. One thing that has been bugging me is how do I call a constructor from another subclass to another. I still haven't grasped that idea or know how to do it.

That happens automatically. When you create an object of a given class, then not only is the constructor of that class called automatically, but so are the constructors of the base classes.

If the constructor(s) of your base classes need to take arguments, then there's a syntax for defining how the constructor of the subclass passes arguments to the constructors of the base classes. Your textbook should explain that.

6. On the member function "makeWithdrawal()" should I keep it as a Void function or should I make it to a boolean function?.

That's up to you. Do you want it to be able to pass information back to the calling code in the form of a boolean?
Last edited on
So far, I've been doing good with the assignment. Bit of slacking off but so far so good. I've stumped into a problem and it involves overloading an operator. I have made an attempt and I am not sure if this is correct. It involves a constructor inside the Base Class which is Account, and the Customer Class.



1
2
3
4
5
6
7
8
9
10
11

//This is the constructor inside the Base Class
Account(Customer custo, double b)
	{
			balance = b;
			cust = custo;
			/*a two-argument constructor which sets balance to the value of the first parameter, 
			a floating point value entered by the user in the test driver, and sets cust to the value of the second parameter, 
			the Customer variable c created and initialized in the test driver, using the overloaded assignment operator of the 
			Customer class*/
	}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//This is the overloaded operator which I have no idea if its correct
Customer& Customer::operator= (const Customer& right)
	{
		name = right.name;
		return *this;

/*an overloaded assignment operator to copy the Customer object instantiated by the test driver to the 
Customer member variable of the Account instance also created in the test driver as 
shown in the following excerpts of the test driver:

Customer c (custName, acctID);
acctsPtr[aNum] = new Checking (c, startBal, overdraftOk);
//OR
Customer c (custName, acctID);
acctsPtr[aNum] = new Savings (c, startBal, intRate);
 */
	}
Help would be appreciated on the overloading operator
If Customer only contains one field (name), then it looks fine to me. Just remember to check for self-assignment as it might be important in other classes.
Thanks! and it does contain one field name.

Self-assignment?. Maybe Im over thinking it but can you go into more detail about that please.
For every class you need a .cpp and a .h file, so 4 classes = 8 files, and then 1 main.cpp gives you a total of 9 files.

I saw this addressed, but I wanted to say, wtf?! You do not just blindly separate every class into its own files (declaration in header and definitions in cpp file). You should use some thought in your design and the files should be named according to what the classes and functions in the file pertain too (Graphics, Network, Input, Sound, etc.) then in each file have the classes and function declarations in graphics.h, network.h, input.h, sound.h, etc. with the definitions in the corresponding cpp file (graphics.cpp, network.cpp, etc.).
Why is everyone going apeshit on his response?lol
My assignment does have 4 classes which are the header files Account/Checking/Saving/Customer
I also have .cpp files corresponding to the headers such as Account.cpp/Checking.cpp/Saving.cpp/Customer.cpp. Then I also have a Test.cpp Which contains the int main() In total thats 9 files. Sure, he might be wrong in other cases but in this case he is correct. Which is why he replied to this topic with that response.
Everyone is going apeshit because he is wrong, even for an assignment, and whoever gave you the assignment appears to be making it way harder to do. Just blindly having students push classes into their own files is a bad habit that is being reinforced by this method. All of those classes are connected and could be in a single file. Or I could be overthinking this, but to me it is:

A customer HASA account
Checking ISA account
Saving ISA account

All perfectly able to be in one or two header(s) and one or two CPP file(s) then the file with the main function. You could easily have account.h/account.cpp for base and derived classes, customer.h/customer.cpp, and then the file with main().

I'd be butting heads with the professor that gave this assignment if it was my assignment. If it is a self-assignment for learning..you are forcing yourself to do poor programming habits. You obviously have to do it the way the professor says, but just remember that he is teaching you a terrible method.
BHXSpecter wrote:
you are forcing yourself to do poor programming habits. You obviously have to do it the way the professor says, but just remember that he is teaching you a terrible method.
Why is it a terrible method? It is pretty common to give a class its own header and implementation files.
naraku9333 wrote:
Why is it a terrible method? It is pretty common to give a class its own header and implementation files.

Yes it is a common method, doesn't make it a good method. Everything I have ever read and instructors said the point of a header is to put all relevant classes, functions, macros, etc. into one header/cpp file. Putting one class per header/cpp file is adding more hassle to your project than needed. The assignment is a simple program that could have the account, checking, and savings classes in account.h and account.cpp (as checking and savings ISA account) then customer.h and customer.cpp (as customer HASA account) and the main file with int main().

Looking at the assignment, I think it is odd anyways. Why make them make 9 files when in reality the three could be set up so that checking and savings could inherit from account then have customer have an account for checking/savings member. That would shrink it down to an account.h/.cpp file that has account (base) checking (derived from account) and savings (derived from account), then customer.h/.cpp and then main.cpp
As someone who's spent a lot of time working on large projects, I can say that breaking your file structure down so that each class has its own header and source file is a very good practice to get into the habit of doing. Once you start working on projects of a significant size - and with significant compilation times - the ability to fine-tune your header dependencies, and reduce compile times, by including only those classes you need to use is invaluable.

Enormo-headers that try and contain too much stuff in one place can introduce a lot of unwanted dependencies that can cause your compile times to increase massively, and can make maintenance and bug fixing much harder. Small, self-contained translation units, sensibly organised, make managing your dependencies so much easier.

Obviously, no rule is true 100% of the time. As one becomes a more experienced developer, one starts to learn when it's appropriate and advantageous to group a lot of things together in one translation unit, and when it's not. But I think one-class-one-unit is absolutely the right way to go when you're just beginning. It's much better to start out by learning those practices which are generally good ones, and then learning to be more flexible when you have enough experience to make that judgement.

I think it's a very good thing that the OP's teacher is demonstrating good practices right from the start, rather than encouraging bloated translation units. I wish more people whose code I've been unfortunate enough to maintain had been taught to do that.
Well, I can't really voice an opinion on this since I am just learning how to code. I do know there are many different methods of coding specific projects but I gotta do what I'm assigned to do haha. Definitely keep all your guys advices in mind :).


Now, can any of you help me when this problem I have.

1.In the test.cpp file my professor declared two things NAME_SIZE and ID_SIZE. Now she gave us a hint that they are both suppose to be declared in Customer Header File. Whenever I try to declare them inside the class. My constructors end up getting weird errors might be because I am declaring them wrong. I am declaring them as const. That might be it.

2.Also in my private member variables, is it safe to declare them as "string" or does one of them have to be an array?.


1
2
3
4
5
6
7
8
int main()
{          
            Account* acctsPtr [MAX];
            char acctType;
            bool validType = true;
            char custName[NAME_SIZE];  //Alternative:  string custName;
            char acctID [ID_SIZE];     //Alternative:  string acctID;
            double startBal;


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
CUSTOMER HEADER FILE
#ifndef CUSTOMER_H
#define CUSTOMER_H
#include <iostream>
#include <string>
using namespace std;

class Customer
{
private:
	string name; 
	string accountID; //which is a c-string or a string (your choice) for the customer's account number which you may assume consists of 6 digits.

public:
	

	Customer()
		{
			name = " ";
			accountID = " ";
			//which initializes each of the member variables to the null string (an empty string)
		}
	
	Customer(string sname, string accID) //which sets the name and accountID to the user supplied values.
	{
		sname = name;
		accID = accountID;


	}
	virtual void view(); //displays the name of the customer and the account number
	Customer& Customer::operator= (const Customer& right)
	{
		name = right.name;
		return *this;

	}
/*an overloaded assignment operator to copy the Customer object instantiated by the test driver to the 
Customer member variable of the Account instance also created in the test driver as 
shown in the following excerpts of the test driver:*/
};

#endif 
Pages: 12