C++ STL vector of pointers

I have been set an assignment which is write a program for a savings scheme. I have quite alot of it so far but I am stuglling of a certian part of my program. My assignments asks to use a STL vecotr of pointers to Member to represent the scheme. I have been looking at vectors for days now but I cannot seem to understand how to use them. Parts of my code so far is below:
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
using namespace std;

#ifndef MEMBER_H
 #define MEMBER_H

class Member{

	public: 
		Member(string, int, date);
		Member();
		virtual Member~();
		void makeDeposit(double amount);
		
		void menu();
		void createMemberMenu();
		Date getExpiryDate();
        void makeDeposit(double);
        virtual double getBonus() = 0;
        virtual void createMember()=0;   
	   	virtual void printDetails()=0;
    
	protected:
   		double balance;
   		int accNum;
   		string name;
   		date expiryDate;
   		string member_type;
};

#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
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
#include "member.h"
#include "date.h"
#include <iostream>
#include <date>
using namespace std;




///////// BankAccout member functions /////////////////////////

Member::Member (string n, int a, Date ex)
{ 
     name = n;
     accNum = a;
     expiryDate = ex;
}


//default constructor which sets the default values
Member::Member()
{
     name = "John Smith"
     accNum = 1000
     expiryDate = 12/12/2001

 

// functions that modify the balnce
void Member::deposit (double balance)
{
   balance + deposit = amount;
}

void Member::withdraw (double balance)
{
	balance - withdraw = amount;
}


// accessor functions 
double Member::getBalance() const  
{
	return balance;
}

double Member::getBonus()
{
// pure virtual function so nothing to do here
}


int BankAccount::getAccNum() const
{
	return accNum;
}

//functions to directly display details
void Member::printDetails()  const
{
   cout << name << ", " << accNum << ", " << balance << endl;
}


//main program
int main() 
{
account acct;
char ch;
Member.menu();

vector<int> v;
int i =10;
v.push_back(i);//fetch an element
cout << v[0] << endl;

        
return 0;
}//end of main program

void createMemberMenu()
{
char selection
cout << "Please select the type of account that you wish to add" << endl;
cout << "<J>unior or <F>ull Member" << endl;
cout << "or press 0 to return to previous menu ..."<<endl;

{
      switch(selection)
      {
      case 'J':
           JuniorMember.createMember();
           break;
      case 'F':
           FullMember.createMember();
           break;
      default:
           Member.menu());
           break;     
      }//end of switch
}
}


void createMember()
{
//pure virtual function so nothing to do
}

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
class JuniorMember:public Member{
  	public:
    	
        JuniorMember(string num, int amount, Date); 
        JuniorMember(); 
        
        void makeDepoist(double);

        double getBonus();
    	void createMember();
    	void printDetails();
 
	private:
		
        int age;
        double depositlimit;
        double bonusRate;
   
};
    



// these function modify the savings account balances

void JuniorMember::makeDeposit (double amount)
{
 Member::deposit();
 If (amount > 10)
 {
    amount = 10;
    cout << "The amount deposited was over the value permitted for a Junior member, so only £10 has been deposited";
 }   
}


// multiplies the balance by interest rate for very simple calculation 
// for positive values of balance 
double  SavingsAccount::calcInterest()
{
	if (balance > 0.0 )
		return intRate * balance;
    return 0;
}

double SavingsAccount::getRate() const      
{
    return intRate;
}
   
// The base class printDetails function is re-defined here

JuniorMember::~JuniorMember() //destructor
{

}                 
   
double JuniorMember::getBonus()
{
   bonusRate = 5.0      
}




//creates/adds data to a file called junmembers.txt
void createMember()
{
string a;
string n;
int bal;
int aNum;
date date;



    ofstream jun;//"jun" refers to members file
    jun.open ("members.txt" ios::app | ios::out);

    if (jun.fail ())
    {
     cout << "Error opening file, program closing" << endl;
     exit(1);
    }

cout << "Please enter a name" << endl;
cin >> n;
cout << "Please enter an age" << endl;
cin >> a;
cout << "Please enter an expiry date" << endl;
cin >> date;

if (a > 16)
{
 cout << "Age of over 16 entered, please change account type (press C) or enter correct age (A)" << endl;
 char op;
 switch(op)
             {
                case 'C':
                	Member.menu();
                	break;
                case 'A':
                	cout << "Please re-enter age (must be 16 or below)" << endl;
                	cin >> a
                	break;
               	default:
                    cout << "Invalid choice, program closing" << endl;
                    exit (1);

}

srand ( time(NULL) ); // this seeds the random number so it will not be dulplicated

aNum = rand() % 999 + 1000;/* The random number generator here is producing a

                         random number between 0 and 999 and then will make the

                         random value be within the range of +1000 - +1999 as it is

                         addingg 1000. Accounts with numbers begining with 1 will be 
                         
                         Junior accounts and accounts with numbers beggining 
                         
                         with 2 will be Full accounts */
                         


bal = 0 //default balance will be nil or 0


jun << n << " " << aNum << " " << bal << " " << a << " " << date << endl;//output to file
}



I have only shown bits of my code but my savings program has two member types. The user can create a member, and the program writes this data to file in the format (Name, account Num, balance, age, expiry date). What I would like help on is how do I use a C++ STL vector of pointers to Members to represent the scheme so that these varibles can be used in my programs functions. As you can probably tell I am using seperate compilation on this program. I have four classes, Date, Member, JunMember and FullMember.
You're still a little confused on classes.

Line 100: you are trying to use a member function without an object. You can't do that. You must first create a variable (of type 'Member'), then you can use the variable's methods.
1
2
Member someone( "Justin Time", 19843, Date( 2009, 3, 31 ) );
someone.menu();

Make sense?

constructors
A side note on constructors and variable names. A person should, just by looking at "member.h", understand how to use each method and object in it.

Bad example: line 9. What exactly am I supposed to give the constructor? Make sure to give your arguments telling names.

Member( string name, int account_number, Date expiry_date );

Good example: line 12. Both the method and its argument are well-named. The method name expresses what the method does, and the argument name expresses what it does it with: makes a deposit of a specific amount.

Watch your capitalizations. Is it Date or date? etc. How does line 25 work? (Not like you think, I'm sure.)

You can make your constructors better (and cooler) by using initialization lists. You can also combine stuff using default arguments if you want. Finally, take const arguments whenever possible (it gives you cool superpowers when using the constructor).
1
2
3
4
5
6
7
8
9
10
11
12
13
  Member(
    // The list of arguments with their default values
    const string& name           = "John Smith",
    int           account_number = 1000,
    const Date&   expiry_date    = Date( "12/12/2001" )
    ):
    // This is the initialization list, which initializes the
    // object's fields using the constructor's arguments
    name( name ),
    accNum( account_number ),
    expiryDate( expiry_date )
    // Finally, there's no need to do anything in the body...
    { }


pointers
If you plan to use pointers, you'll need to be familiar with the new and delete operators.
1
2
3
4
5
6
7
8
9
10
11
Member  someone;   // Actually creates a Member named "John Smith", acct 1000, etc.
Member* psomeone;  // Only creates a pointer to a Member or one of its descendants

someone.menu();    // works fine
psomeone->menu();  // causes segmentation fault -- there is no Member here

psomeone = new JuniorMember;  // now it points to an actual Member object
psomeone->menu();

delete psomeone;  // destruct the Member object and free the memory it used
psomeone->menu();  // error again! 


vectors
Well, now to your question. Make sure to keep a reference handy.
This one is pretty good: http://www.cplusplus.com/reference/stl/vector/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// To create a vector, declare it as any other variable.
vector <Member*> all_the_members;

// Add members using one of the insertion routines
all_the_members.push_back( new Member );

// Access the elements
all_the_members[ 0 ]->menu();

// Don't forget to free all memory before the program terminates
for (vector <Member*> member = all_the_members.begin();
     member != all_the_members.end();
     member++)
  delete *member;
all_the_members.clear();


Hope this helps.
first of all, the main thing to remember with STL containers of pointers is to delete the pointer before you erase the pointer from the container, otherwise you'll have a memory leak. Putting the pointer into the container is the easy part, just 'new' an instance of the class and use the push_back http://www.cplusplus.com/reference/stl/vector/push_back.html member of sts::vector to add it to the vector.

To find the member you need to change, either use a for loop, assessing the vector members using the [] operator example here http://www.cplusplus.com/reference/stl/vector/operator[].html or if you're feeling adventurous use iterators and the find algorithm http://www.cplusplus.com/reference/algorithm/find.html You'll have to be clever with find and use bind2nd (http://www.cplusplus.com/reference/misc/functional/bind2nd.html.

Don't forget to delete before you erase at the end.

EDIT: too slow again :)
Last edited on
Thanks for the help guys but the bit I am struggling with is getting the data off the text file and in to the vector. Could someone maybe post a simlilar example or something as I don't really understand this.
Remember, a pointer only references data. It does not create the data.

Also, you should have a pair of functions that read and write a single member to an open file. Typically this is done by overloading the >> and << operators, but it can be done any way.

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
vector <Member*> members;
Member* p_member;
ofstream members_file;

// Get members from the user
while (true)
  {
  p_member = new Member;
  p_member->read( cin, cout );  // we want interactive input, so our read()
  if (!cin)                     // function takes a second argument to ask the user questions
    {
    delete p_member;
    break;
    }
  else
    members.push_back( p_member );
  }

// Write the members to file
members_file.open( ... );
for (unsigned cntr = 0; cntr < members.size(); cntr++)
  members[ cntr ]->write( members_file );
members_file.close();

// free all memory (remember, first delete the referenced memory before
// deleting the pointer to it --as the vector is an array of pointers.
for (unsigned cntr = 0; cntr < members.size(); cntr++)
  delete members[ cntr ];
members.clear();

All you would need to do is write your read() and write() member functions.

Hope this helps.
Thanks for the code, but the format in which the data is stored for a young member is different of the of a full member (juniors sotre and extra varible). How would I get the program to choose the right output file (one is called "youngMembers.txt", and the other "fullMembers.txt"? Please can I also ask how would the data from the file be passed to my programs functions, would it be something like (p_member->JunMem.myFunction)?

Please could you also explain what the following is doing:
1
2
3
4
5
// Write the members to file
members_file.open( ... );
for (unsigned cntr = 0; cntr < members.size(); cntr++)
  members[ cntr ]->write( members_file );
members_file.close();
Last edited on
Topic archived. No new replies allowed.