Constructors are kicking me in the rear!

Pages: 123
Ok, I just started my c++ level two class, after a six year break from level one. I'm not allowed to retake level one unfortunately, so I'm struggling a bit in level two.

My latest assignment has me having to add constructors to my current address book program. I have been trying to do this for almost a week, and for the life of me I just cannot figure out how to get them to work at all.

I'm not looking for someone to answer or solve this for me, but I really need help, and I am desperate. Can anyone please help me understand what I need to do and how to do it.

----------------------------

Here's my header file:

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
#ifndef _ADDRESSBOOK
#define _ADDRESSBOOK
const int MAXADDRESS = 25;
struct PERSON
{
 char fName[25];
 char lName[25];
 char Address[100];
};
class addressBook
{
private:
 PERSON people[MAXADDRESS];
 int head;
 int tail;
 
public:
 addressBook();


 bool addPerson(const PERSON &p);
 bool getPerson(PERSON &p);
 bool findPerson(char *lastName, PERSON &p);
 bool findPerson(char *lastName, char *firstName, PERSON &p);
 void printBook();
 static addressBook *Instance();
};
#endif 



------------------------------------------------



here is my addressbook .cpp file:

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
#include <iostream>
#include "addressBook.h"
using namespace std;
addressBook::addressBook()
{
 head = 0;
 tail = -1;
}
bool addressBook::addPerson(const PERSON &p)
{
 if(head < MAXADDRESS)
 {
 people[head] = p;
 head++;
 if(tail == -1)
 tail++;
 return true;
 }
 return false;
}
bool addressBook::getPerson(PERSON &p)
{
 if(tail >=0)
 {
 if(tail >= head)
 tail = 0;
 p = people[tail];
 tail++;
 return true;
 }
 return false;
}
bool addressBook::findPerson(char *lastName, PERSON &p)
{
 for(int i = 0; i < head; i++)
 {
 if(!stricmp(people[i].lName, lastName))
 {
 p = people[i];
 return true;
 }
 }
 return false;
}
bool addressBook::findPerson(char *lastName, char *firstName, PERSON &p)
{
 for(int i = 0; i < head; i++)
 {
 if(!stricmp(people[i].lName, lastName) && !stricmp(people[i].fName, firstName))
 {
 p = people[i];
 return true;
 }
 }
 return false;
}
void addressBook::printBook()
{
 for(int i = 0; i < head; i++)
 {
 cout << people[i].fName << "\t" << people[i].lName << "\t" << people[i].Address << endl;
 }
}



-------------------------------


and here is my main.cpp:


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
#include <iostream>
#include <cstdlib>
#include <conio.h>
#include "addressBook.h"


using namespace std;
int printMenu();
void waitKey();

const int ADDPERSON = 1;
const int GETPERSON = 2;
const int FINDLAST = 3;
const int FINDBOTH = 4;
const int PRINT = 5;
const int EXIT = 0;
int main()
{

	addressBook ad;


int selection;

PERSON p;


bool status;
char lName[50];
char fName[50];
		

		selection = printMenu();
		while(selection != EXIT )
		{
		switch(selection)
			{
			case ADDPERSON :
				cout << "Enter First Name " << endl;
				cin >> p.fName;
				cout << "Enter last Name " << endl;
				cin >> p.lName;
				cout << "Enter Address " << endl;
				cin >> p.Address;
				status = ad.addPerson(p);
				if(status == false)
					cout << "Sorry There is no more room in the address book " << endl;
				else
					cout << "Thanks for your Entry " << endl;

				waitKey();	
				break;
			case GETPERSON :
				status = ad.getPerson(p);
				if(status)
					cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
				else
					cout << "Sorry The address book is empty " << endl;

				waitKey();

				break;
			case FINDLAST :
				cout << "Enter a last name " << endl;
				cin >> lName;
				status = ad.findPerson(lName,p);
				if(status)
						cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
				else
					cout << "Sorry, Name not found " << endl;

				waitKey();
				break;

			case FINDBOTH :
				cout << "Enter last name " << endl;
				cin >> lName;
				cout << "Enter first name " << endl;
				cin >> fName;
				status = ad.findPerson(lName, fName,p);
				if(status)
					cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
				else
					cout << "Sorry, Name not found " << endl;

				waitKey();
				break;
				
			case PRINT :
				
				ad.printBook();
				waitKey();
				break;
			case EXIT :
				cout << "Thanks for using the address book " << endl;
				exit(0);
			}
			selection = printMenu();
		}
}

int printMenu()
{
	

int selection;

	system("CLS");
	cout << "1. Add A Person" << endl;
	cout << "2. Get A Person " << endl;
	cout << "3. Find A person By Last Name " << endl;
	cout << "4. Find A person By First and Last Name " << endl;
	cout << "5. Print the address book" << endl;
	cout << "0. Exit this program " << endl;
	cin >> selection;

	return selection;

}

void waitKey()
{

	cout << "Press a key to continue " << endl;
	while(!kbhit())
		;

	getch();
	fflush(stdin);

}


-------------------------------------------------


Finally, here are my assignment requirements:


For the addressBook class you created in lab 2 create overloaded constructors that will accomplish the following:

Initialize a single person passing the informaition using three cStrings
Initialize a single person passing the information using a PERSON struct;
Initialize several people passing an array of PERSON structs and an int that holds the count
Make sure that your constructors do not allow you to add too many people to the address book, and make sure you set the count appropriately

Example use:

Constructor 1

addressBook ab("Bob", "Roberts","1313 Mockingbird ln.");



Constructor 2

PERSON p = {"Bob", "Roberts", "1313 Mockingbird ln"};

addressBook ab(p);



Constructor 3

PERSON p[] = {
{"Bob", "Roberts", "1313 Mockingbird ln"},
{"Joe", "Smith, "1023 Anywhere"},
{"Jane", "Doe", "555 self place"}
};

addressBook ab(p, 3);


Thank you in advance for anyone who has the time to help me with this.
Last edited on
First, please edit your original post and add code tags. It makes things so much easier to read, and as a result, will up your chances of getting help.
Second, what exactly are you struggling with? The assignment requirements?
Please explain a little, tiny bit more for us to help you.
What are you struggling with exactly?

The first thing you need to add is declarations for the constructors in question up in your addressBook declaration.

I'd second xismn, code tags would help here. Further to that, just include the code that is relevant. In this case, it's your addressBook class declaration and the implementation of the constructors in question.
OK, I fixed the code like you asked, sorry about that, I didn't see the code tags.

So here's my problem. I understand what constructors are supposed to do, and I kind of understand how they work, but for this assignment, I don't know how I'm supposed to type them out. I suppose it's the syntax I'm not getting.

I've tried several things to get this to work, but even when I can compile and run without any errors, the names I should have stored in the address book when the program runs.

I'm assuming I should have something like this in my header:

1
2
3
4
5
addressBook();

addressBook(PERSON);

addressBook(const PERSON &p);


I don't understand how I'm supposed to take that and post it in main so that it runs correctly, (assuming that is what I actually need in the header)

I've thought about using something like

addressBook::addressBook ab("Bob", "Roberts","1313 Mockingbird ln.");

But I have no idea how to use that so it can be called up in the actual program.

I'm just having a really hard time with this. When I see code that is similar, I usually understand whats going on, but I can't find anything like whats required for this assignment, and I am just lost as to what to do.


Last edited on
Close.

In their implementation, constructors aren't really different to any other functions.

Look at the two example calls your teach has given you:
xanthian23 wrote:
Constructor 1

addressBook ab("Bob", "Roberts","1313 Mockingbird ln.");



Constructor 2

PERSON p = {"Bob", "Roberts", "1313 Mockingbird ln"};

addressBook ab(p);



Constructor 3

PERSON p[] = {
{"Bob", "Roberts", "1313 Mockingbird ln"},
{"Joe", "Smith, "1023 Anywhere"},
{"Jane", "Doe", "555 self place"}
};

addressBook ab(p, 3);


Now, think of those as function prototypes:
1
2
3
4
5
6
7
8
// Constructor 1 - Three character arrays
addressBook( char *fName, char *lName, char *address );

// Constructor 2 - A person object
addressBook( PERSON p );

// Constructor 3 - An array of person objects and a size
addressBook( PERSON *p, int size );


The body of the constructor is adding people to the array of PERSON objects that the class stores based on the information passed in.
OK, see, I've tried all of these in my header file already, and although I don't get any errors from the header file, I can't ever get them to work in my main.cpp.

I tried this in my header file, and got no errors:

1
2
3
4
5
6
7
8
addressBook( char *fName, char *lName, char *address )
	  
	 {
		 fName = "CJ";
		 lName = "CJM";
		 address = "123 Road";
		 
 };


But no matter what I do in main, I can't get it to accept the constructor, or at least not the info inside the parenthesis of the constructor. the second I type

addressBook( char *fName, char *lName, char *address );

in main, it pops up red lines for all the chars, saying that the type name isn't allowed, and the *fName and others are all undefined.

I was told that I shouldn't need to put any of this stuff in the addressbook.cpp, and that everything can be done in the header and main, but I don't know how to call on these functions in main. I've tried using the scope resolution, which I'm pretty sure is needed for this, but I'm always getting errors.

I got main to accept:

PERSON me = {"CJ", "CJM", "123"};

without any errors, and the program ran, but nothing was stored in the program when it ran. I assumed because I hadn't told it what to do with "me", but I don't know how to pop that into the code so it actually works.

As for the array, I'm pretty sure I have to throw in a for loop with the (i=0, i<25, i++) thing to keep the addressbook from throwing in too many names, but I don't know where, or how I'm supposed to do that with a constructor.

Object oriented programming was a lot simpler before they started actually making us use objects.
Last edited on
Ok.

Let me give you one of them. See if it helps.

1
2
3
4
5
6
7
8
9
10
11
12
// In header (class definition)
addressBook( PERSON p );

// In cpp (declaration)
addressBook::addressBook( PERSON p )
{
   addPerson( p );
}

// Creation, assuming you have a person object
// Let's call it myPerson
addressBook myAddressBook( myPerson );
Last edited on
OK, I used the

addressBook( PERSON p );

in my header, and then I popped the

1
2
3
4
addressBook::addressBook( PERSON p )
{
   addPerson( p );
}


into my addressbook.cpp file, and then in my main I did this:

1
2
3
4
5
addressBook ad;

	PERSON me = {"CJ", "CJM", "123"};
	addressBook myBook( me );
	ad.addPerson(me);


And that actually worked! When I ran the program, the name was stored in memory. So, first off, did I do that correctly, and then secondly, assuming I did do it correctly, how or why did that work?

I'm guessing I created a person object with the PERSON me, and gave "me" the required set of inputs that PERSON is set up to take in. I'm also guessing that using addressBook myBook(me) called the constructor and had it make something called myBook which calls the info from "me", and then I used the ad.addPerson, called the "me" to it, which then added the info from me into the actual addressbook memory. Is that right?
Last edited on
In that constructor, you're basically defining how the class behaves if it's created given a PERSON object.

You created it in this way using this line:
 
addressBook myBook( me );


That creates an address book with one person. The person has the details given in object you created the line before.
Ok, how do I do the first part then? I put this in main:

addressBook part1("TEST", "TEST", "TEST");

But since it's not a part of PERSON, I can't call it to the addPerson like I did on the previous one. I've tried this in my header:
1
2
3
4
5
6
7
addressBook part1(char *lName, char *fName, char *addy)
 {
	 lName = "TEST";
	 fName = "TEST";
	 addy = "TEST";
	 
 };


and then just putting:

addressBook part1;

in main, but still no go.

I guess what I'm trying to figure out is how do I get those three strings to pop into PERSON without doing the exact same thing I did before... or is that what I'm supposed to do?

The best I can tell, it seems like all my problems are stemming from not being able, or at least, knowing how, to make this pop itself into PERSON. Anyone know how I can do that?

And thank you so much iHutch for all the help so far, you've taught me more here in this forum than I've gotten anywhere else.
Right, let's clear a couple of things up here.

First of all, let's look at your code from a couple of posts ago...

1
2
3
4
5
addressBook ad;

PERSON me = {"CJ", "CJM", "123"};
addressBook myBook( me );
ad.addPerson(me);


You're creating two addressBooks here. One called ad and once called myBook. Let's forgot about ad, we're not concerned with it. Leaving us with two lines:

1
2
PERSON me = {"CJ", "CJM", "123"};
addressBook myBook( me );


Ok, now remember that a constructor implicitly runs when a class is instantiated. That's the second line in the code above. By default, the constructor for any class in which you don't override it doesn't take any arguments.

So you have a scenario where you want to give the class object some arguments right away. The default constructor won't do, so we need to write our own. As established a few posts ago, we need three different versions of our constructor:

1
2
3
4
5
6
7
8
// Constructor 1 - Three character arrays
addressBook( char *fName, char *lName, char *address );

// Constructor 2 - A person object
addressBook( PERSON p );

// Constructor 3 - An array of person objects and a size
addressBook( PERSON *p, int size );


So, we want to tell our class how to behaviour if it's created and given:
1) Three strings
2) A PERSON object
3) A list of PERSON objects

This will allow us to create objects in the following ways:
1
2
3
4
5
6
7
8
// Three strings
addressBook myBook( "John", "Smith", "Somewhere" );

// A person object
addressBook myBook( somePerson );

// A list of person objects
addressBook myBook( somePeople, 3 );


We've already gone through the code for the second one - the construct takes the PERSON that has been passed to it, and calls the addPerson function to add the entry to the list. This effectively results in a book created with one entry - the person passed in.

The first and third I'll do in pseudocode, because it's important that you get the concept behind what we're doing.

The first. We have three strings. Given their names, we can safely assume what they represent; a person's forename, surname and address. This constructor will provide a similar result to number two - it'll create an object with one person already added. That person will have the details passed in using the strings. So let's look at what we need to in the constructor.
- Create a person object, based on the data passed in
- Call addPerson, passing in the person we've just created


That's it.

The third construct assumes an array of people have been created. We need to pass the size of the array too, as we need to know how many people to add. We need to loop through the number of entries passed in and call addPerson for each one. It'll look like this.
Begin loop - for i < size
   - Call addPerson for p[i]
End loop


A couple of notes on your last post:

In your header, only have the constructor definitions. No declarations. In some of these, ideally you'd use initialisation lists, but that's not a concern right now.

xanthian25 wrote:
I guess what I'm trying to figure out is how do I get those three strings to pop into PERSON without doing the exact same thing I did before... or is that what I'm supposed to do?

Your teacher gave you an example of this in his code. It's this:
 
PERSON p = {"Bob", "Roberts", "1313 Mockingbird ln"};


xanthian25 wrote:
And thank you so much iHutch for all the help so far, you've taught me more here in this forum than I've gotten anywhere else.

You're most welcome. I've got more than enough time for those who want to learn. :-)
OK, so I have this in my header:

addressBook( char *fName, char *lName, char *Address );

From there I popped into the addressbook.cpp file and typed in this:

1
2
3
4
5
6
7
8
addressBook::addressBook( char *fName, char *lName, char *Address )
 {

	 fName = "MAN";
	 lName = "DAN";
	 Address = "123";

 };


I'm guessing thats how I get the name into the constructor for the first part, which I think is pointing to PERSON

So my question is, how on earth do you get that to pop up in main so it stores the name in the program?

Aside from the hour I spent last night cramming in the homework for my other classes, I have been at this all week, practically non stop, day and night, and I cannot get this to work. I have tried tons of stuff, but there is just something I am not getting, and it's so frustrating I want to kick something.

When you say
- Create a person object, based on the data passed in
- Call addPerson, passing in the person we've just created
I'm not totally clear on how to do that.
would it be like making a constructor like this

addressBook test( "FIRST", "LAST", "ADDY");

and then adding "test" to PERSON:

1
2
3
4
PERSON test
{addPerson (p)
};


Is that what I should be doing? If so, how do I get it into the stored memory from main?

I'm sorry it's taking me so long to get this. After a week of reading and trying everything I can think of, I understand what a constructor is, and what it can do, I'm just loosing my mind trying to understand how to do anything with it.

OK, I have this in main:

addressBook myBook("TEST", "TEST2", "TEST3");

and I know that it is pulling from my string set in my header:

addressBook( char *fName, char *lName, char *Address );

How do I get this into addPerson?

my PERSON insert I did had this setup:

1
2
3
PERSON me = {"Someone", "Somebody", "123 house"};
	addressBook myBook(me);
	ad.addPerson(me);


that called the PERSON struct, added the object "me", set the names, and then I added "me" to my address book "myBook", then used ad.addperson to slap "me" into addperson.

So how do I get a string setup like I have to go into the addressbook through the addperson?
1
2
3
4
5
6
7
8
addressBook::addressBook( char *fName, char *lName, char *Address )
 {

	 fName = "MAN";
	 lName = "DAN";
	 Address = "123";

 };


fName, lName and Address are variables that are being passed into your constructor remember. You don't need to assign anything to them in there - they're already populated with data sent from the call.

What you need to do, is create a person object based on the what has been passed in.

The example code for this was given by your tutor.
 
PERSON p = {"Bob", "Roberts", "1313 Mockingbird ln"};


All you need to do is create a person in the same way, only rather than giving it "Bob", "Roberts" and "1313 Mockingbird lb", give it the variables that have been passed into the constructor.

Then, just call addPerson, passing in the person you've created.
Didn't I already do that with PERSON me?

1
2
3
PERSON me = {"Someone", "Somebody", "123 house"};

	myBook.addPerson(me);


or is this something else?
That's something else.

What you're doing there is creating a person, then calling the addPerson function of an addressBook that already exists.

Remember, constructors run implicitly when the object is created.

For example:
1
2
3
4
5
6
addressBook myBook; // Default c'tor runs here

addressBook myOtherBook( "Bjarne", "Stroustroup", "Cppville" ); // Overloaded c'tor runs here

addressBook *myDynamicBook;
myDynamicBook = new addressBook; // Default c'tor runs here 

Ok, you may have lost me on this one.

So I'm making a new addressbook, which uses my constructor with the strings in the header file I get that.

.h
addressBook( char *fName, char *lName, char *Address );

main
addressBook newbook("TEST", "TEST2", "TEST3");

but what does
addressBook *myDynamicBook;
myDynamicBook = new addressBook; // Default c'tor runs here


that have to do with it? since I'm using "ad" as my main book, would I be doing it
1
2
addressBook *ad;
ad = newbook;


No, never mind, I just tried it. I don't get it. I'm really starting to wish they would have let me retake level one, because there is obviously something I'm missing. It shouldn't take me all week to not understand a stinking lab assignment, and I haven't even started trying to work out the array yet. I completely understand whats going on with with the PERSON one that works, I even explained it to my son and he understood it from what I told him. I'll keep trying.
Ok, ignore the new. I was using dynamic memory to indicate when a constructor runs. I'd wrongly assumed you might have already covered this. For the time being, it isn't important.

From your last post, your header file is correct. Don't change it.

Your code from main is also right. Providing you've implemented the constructor correctly, it should create an address book with one entry, which has a first name of "TEST1", a surname of "TEST2" and an address of "TEST3".

So you should be writing the body of the constructor in the addressbook.cpp file. Why don't you show me what you have for this constructor and we'll make sure it's doing what it should be.
Last edited on
I have this:

1
2
3
4
5
addressBook::addressBook( char *fName, char *lName, char *Address )
 {

	 bool addPerson(const PERSON &p);
 };


But since it isn't doing anything, I've already assumed it wrong. MY teacher had said that we shouldn't need to put anything in the addressBook.cpp file, but that just hasn't made any sense to me, butcause everything I've seen so far seems to say otherwise.

I tried just throwing in addPerson(p);, but the compiler didn't care for that.
Pages: 123