How to make a private member accesible outside the class?

The question says that:
Define a class ACCOUNT with the follwing members:
Private Members:
      Acno     of type int
      Name     of type char array size of 20
      Balance  of type float
Public Members:
      void Init()      member function to enter values of data members
      void Show()      member function to display the values of data members
      void Deposit(int Amt)      member function to increase Balance by Amt
      void Withdraw(int Amt)     member function to reduce Balance by Amt
      float RBalance()           member function that returns the value of Balance

(1)Define a function Register(), to create a binary file named Accounts.dat, which should contain details of ACCOUNTs entered by a user.

(2)Define another function Transact(), to perform a transaction i.e Deposit or Withdraw an Amount in an Account Holders Balance whose Acno is entered by the user. Note that an Account Holder must always have a minimum Balance of $500.

(3)Define another function DisplayAll() to display the details of all Account Holders.

Write a menu driven program, which uses all the above functions.


For this I made the following program:

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
#include<fstream.h>	
#include<conio.h>
#include<stdio.h>
#include<string.h>

class ACCOUNT
{
private:
	int Acno;
	char Name[20];
	float Balance;

public:
	
	void Init();

	void Show()
	{
		cout<<"Account Number: "<<Acno<<endl;
		cout<<"Account Name: "<<Name<<endl;
		cout<<"Account's Balance: "<<RBalance()<<endl;
	}//void Show() closes.

	void Deposit(int Amt)
	{
		Balance+=Amt;
	}//void Deposit() closes.

	void Withdraw(int Amt)
	{
		Balance-=Amt;
	}//void Withdraw() closes.

	float RBalance()
	{
		return Balance;
	}//float Rbalance() closes.

};//Class closes.

void ACCOUNT::Init()
	{
		cout<<"Enter Account number: ";
		cin>>Acno;
		cout<<"Enter Account Name: ";
		gets(Name);
		do
		{
         cout<<"Enter the account's balance greater than or equal to Rs.500: ";
		 cin>>Balance;
		}while(Balance<500);
	}//void Init() closes.

void Register()
{
	fstream fil;
	fil.open("Accounts.dat", ios::binary|ios::out);
	ACCOUNT S;
	char ch;
	do
	{
		S.Init();
		fil.write((char*)&S,sizeof(S));
		cout<<"More(y/n)?: ";
		cin>>ch;
	}while(ch=='y');
	fil.close();
}//void Register() closes.

void Transact()
{
	ACCOUNT S;
	int Acno, choice, withdraw, deposit;
	cout<<"Enter the Account Number to whom you want to Deposit or Withdraw money: ";
	cin>>Acno;
	if(Acno==S.Acno)
	{
		
			cout<<"1. Withdraw Money."<<endl;
			cout<<"2. Deposit Money."<<endl;
			cout<<"Enter your choice: "<<endl;
			cin>>choice;
			switch (choice)
			{
			 case 1:
				 {
					 cout<<"Enter the amount of money you want to withdraw: ";
				     cin>>withdraw;
				     if(S.RBalance()-withdraw<500)
					  cout<<"You cannot withdraw such an amount of money as this makes the balance of the account less than Rs.500."<<endl;
				     else
					  S.Withdraw(withdraw);
					 break;
				 }
			 case 2:
				 {
					 cout<<"Enter the amount you money you want to deposit: ";
					 cin>>deposit;
					 S.Deposit(deposit);
					 break;
				 }
			 default:
				 {
					 cout<<"Incorrect choice."<<endl;
					 break;
				 }
			}//Switch Case closes.


	}//if loop closes.
}//void Transact() closes.

void DisplayAll()
{
	ACCOUNT S;
	cout<<"The details of all the account holders after the transactions you made are: "<<endl<<endl;
	S.Show();
}//void Transact() closes.

void main()
{
	clrscr();
	Register();
	Transact();
	DisplayAll();
	getch();
}//void main() closes. 


But, the error comes as:
Line 76: ACCOUNT::Acno is not accessible.


But then the 2nd part of the question itself says that "Acno entered by the user". So we need to identify/search for an account with that Account Number. How can we do this without comparing Acno with S.Acno? I know that S.Acno is not accesible as it is a private member but then how to compare Acno without even using a member function(public) that can return the value of Acno?
Help Please!


Declare transact function as a friend function of Account class.
 
friend void Transact();

put this under ur classes publc scope.
Seen as you only have one account (even if you multiple accounts), all your functions should be members of the class.

If you had multiple accounts (which is a much more likely scenario), in another class which had a collection of Account objects (vector or array or some other container), then this class would have an interface of public functions to allow one to interact with an account.

Remember, class functions have direct access to all member variables. So take advantage of this by putting the functions into the class.

This concept is part of the idea of encapsulation - meaning that generally all of the data and functionality of an object should be in that object's class.

@anirudh sn
Using Friend functions is not a particularly good idea in this situation IMO.

Hope all goes well.

EDIT: It is int main() not void main()

At the moment all you r function use local Account objects which are not constructed with anything and are of type void, and I don't see where the Init function is called from. More good reasons to put the functions in the class.
Last edited on
@IdeasMan:
declaring as a friend is the only way by which one can give access to a private member of a class to a non member function, as far as usage is concerned whether to make the function as a friend or make it a member of the same class, its left to him, he should figure it out!!!
anirudh sn wrote:
..... as far as usage is concerned whether to make the function as a friend or make it a member of the same class, its left to him, he should figure it out!!!


Well, yes - I was advising the OP to use a member function, which I think is a much better idea than a friend function. I think it is better to suggest good design practices, rather than simpler but less than optimal ones.
Winkerd (68):

neither friend function nor adding every function as a member function just to gain access to private members is optimal, the standard practise is:

write getter and setter methods for private variables make these methods public.

ex:

1
2
3
4
5
6
7
8
void setbalance(float balance_param)
{
  Balance=balance_param;
}
float getBalance()
{
return Balance;
}

place them in public section of class, whenever u need to access/manipulate the private members of class,call getter/setter methods on the object and pass relevant values.Now thats a better practise.
Last edited on
anirudh sn wrote:
neither friend function nor adding every function as a member function just to gain access to private members is optimal, the standard practise is:

write getter and setter methods for private variables make these methods public.


Now thats a better practise.

It is absolutely NOT better practise, and neither is it standard practise

Getters are reasonably benign, but setters that are straight assignment are really bad news. Having member functions and constructors with initialiser lists is much better than having get / set functions. Update functions that have checking and / or validation are a different matter. We had a huge discussion about it here:

http://www.cplusplus.com/forum/lounge/101305/


Having public get / set functions for each member variable is the same as having them all public. And doing this is a common misconception for beginners.

One example of why setters are bad:

anirudhsn.SetBalance(-1000000.00) // instant mortgage 1 million dollars !!

Another key point is that one should hide the objects data from the outside world, get / set functions destroy that notion. That is why I mentioned the idea of encapsulation in my earlier post.

Also, when one has get / set functions, there are a lot of trivial functions (more code) as opposed to a few worthwhile functions to do the same thing.

When data needs to be legitimately available to other classes, then provide a proper interface of functions to do that, or use send / receive functions, or design patterns.

I am not saying that they shouldn't be used at all, just that this is a classic situation where they are used very poorly.



Getters are reasonably benign, but setters that are straight assignment are really bad news. Having member functions and constructors with initialiser lists is much better than having get / set functions. ...

u cant invoke a constructor just to set/reset the values, constructors vs setters is not a valid comparison!!!

One example of why setters are bad:

anirudhsn.SetBalance(-1000000.00) // instant mortgage 1 million dollars !!

Ive seen getters/setters in many real time applications, for some critical cases getters/setters are made protected/not given, it is nonsense to say that getters/setters are not used.
Tell me how do u think balance info is fetched from a bank acc?? its a getter method, getter and setter methods are evrywhere, if the variable is very critical then they are not provided or made private!!!
@anirudh sn
I think it would be worth your while to read the discussion in the link I provided.

anirudh sn wrote:
u cant invoke a constructor just to set/reset the values, constructors vs setters is not a valid comparison!!!


But a constructor with an initialiser list can set values initially and might mean there is no need for set functions at all. I did mention update functions, and I did mention the naivety of having straight assignment in a set function. And I also said get functions are rather benign.

anirudh sn wrote:
Ive seen getters/setters in many real time applications, for some critical cases getters/setters are made protected/not given, it is nonsense to say that getters/setters are not used.


I also said:

TheIdeasMan wrote:
I am not saying that they shouldn't be used at all, just that this is a classic situation where they are used very poorly.


And I was talking about public set functions.

anirudh sn wrote:
Tell me how do u think balance info is fetched from a bank acc?? its a getter method, getter and setter methods are evrywhere, if the variable is very critical then they are not provided or made private!!!


Would you care to tell us what your bank balance is right now? Or even better should there be a way I can look it up on the net without even asking you, then transfer your money to my account? Again I am talking about public functions. Which is what you proposed to the OP. You also proposed friend functions, but again this isn't appropriate for this situation.

What I mean is that there may be a get function used internally, but it certainly should not be public. Think of an ATM machine - there would be layers between the ATM and the actual account. After identification and authorisation, the ATM class makes a transaction request to the Transaction class, which queries the account class and decides whether the transaction can be approved. There is no ATM.Withdraw("anirudh sn", 100000.00) function that works directly on your account. The account class is unknown to the ATM class.

So, for the OP's program. I see it like this:

There is just an Account class, plus some container for putting them in.

We need to set values when the account is first created - name & other personal details, an initial balance of 0.00. This can be done with a constructor with an initialiser list, provided that an STL container is used to store them, so we can call the constructor with arguments and use it's initialiser list. So no set functions needed here.

If an array is used (the default constructor is called, so values are already initialised), then one could have a small number (or even just one) of set functions that set several member variables inside the function - SetName, SetAddress, SetDOB etc say. We do not have a set function for each member variable, and they have checking, validation, identification & authorisation checks. They are not just straight assignment.

The two Update (mutator) functions that are needed as a minimum are Deposit & Withdraw. Others such as change address might also be required. These are public functions that take arguments, do checking & validation, and are not straight assignment.

Printing out values is also a member function, it has direct access to the member variables. It is poor form to use get functions from main() for this purpose.

Finally, I think the topic of get /set functions falls in the list of things that are often done routinely & badly by beginners (they frequently point to bad design), but there are some valid situations for their use. Beginners often do this because they see it as being easier, Some of these might be:

- Infinite loops
- get / set functions
- goto
- friend functions / classes
- dynamic casting
- RTTI


the standard practise is:

write getter and setter methods for private variables make these methods public.


jeez, who told you this is standard practice? No offence but you're giving some pretty bad advice out.
@OP

Instantiate ONE ACCOUNT object in your main function and call all your methods off this.

I dont think this is doing what you think it's doing:
1
2
3
4
5
6
void DisplayAll()
{
	ACCOUNT S;
	cout<<"The details of all the account holders after the transactions you made are: "<<endl<<endl;
	S.Show();
}



When you call S.Show() you are by defination calling this stuff:
1
2
3
cout<<"Account Number: "<<Acno<<endl;
		cout<<"Account Name: "<<Name<<endl;
		cout<<"Account's Balance: "<<RBalance()<<endl;


but for that ACCOUNT object you created in the show method you have not set Acno, Name or RBalance, so you'll be printing out garbage values.

Ideally have your void DisplayAll() take an Account object:

void DisplayAll(ACCOUNT& myAccount)
, pass in the account object i said to create in main, and use this in DisplayAll. i.e.

1
2
3
4
5
6
void DisplayAll(ACCOUNT& myAccount)
{

	cout<<"The details of all the account holders after the transactions you made are: "<<endl<<endl;
	myAccount.Show();
}


Last edited on
Topic archived. No new replies allowed.