The first and second error was just that you had used "->" on an object. You had need to use "." which is how to reference a member on an object, while "->" is how to reference a member on a pointer. Then once that bug was fixed, the compiler complained (third and fourth errors) that there was no GetName() method because the vector class does not have that method. To get the "value" stored at some index of the vector, you can just use array notation as I show below.
The fifth error occurs because the method displayWifeChildren is a member of the Male class and you called it as if it was just a method (not in a class).
You might want to try ((Male *) arr[i]) -> displayWifeChildren (arr) instead.
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
|
class Male: public Person
{
public:
Male (string name, int ID, string gender) : Person(name, ID, gender)
{
}
void addWife (Person *arr [], string p1, string p2);
void displayWifeChildren (Person *arr [])
{
for (int i = 0; i < wife.size (); i++)
{
cout << wife [i] -> getName () << "\n";
for (int j = 0; j < children. size (); j++)
{
cout << children [j] -> getName () << "\n";
}
}
}
private:
vector <string> wife;
};
The current version is the following ...
class Male: public Person
{
public:
Male (string name, int ID, string gender) : Person(name, ID, gender)
{
}
void addWife (Person *arr [], string p1, string p2);
void displayWifeChildren (Person *arr [])
{
int i = 0;
int j = 0;
while (i < wife.size () )
{
cout << wife [i] -> getName () << "\n";
cout << wife [i] . getName () << "\n";
cout << wife [i] << "\n";
while (j < children.size () )
{
cout << children [j] -> getName () << "\n";
cout << children [j] . getName () << "\n";
cout << children [j] << "\n";
}
}
}
private:
vector <string> wife;
};
void displayChildren (Person *arr[], string p1)
{
int SIZE = 10;
for (int i = 0; i < SIZE; i++)
{
if (arr [i] -> getName () == p1)
{
cout << "Children of " << arr [i] -> getName () << " are ";
displayWifeChildren (arr);
((Male *) arr [i]) -> displayWifeChildren (arr);
}
}
cout << "\n";
}
|
To answer the last question:
Yes, it would be nice to put a displayChildren method in the Female class, and have another method displayWifeChildren in the Male class. This would make the method in the Male class almost trivial, while most of the current logic you have in Male can be moved into the displayChildren method of the Female class.
Another solution which would make your code a little safer as far as type-checking (albeit at the slight expense of virtual functions), is to declare a virtual method (it could be pure virtual or not, whatever suits you) in the Person class:
virtual void displayChildren() {}
or
virtual void displayChildren() = 0;
Then in both the classes Male AND Female, implement a method of the same name:
Male {
void displayChildren() {}
Female {
void displayChildren() {}
The Male's method could then just call the Female's method, and there is one more very big advantage: We would no longer need to cast the Person * arr[i] to a Male *. The overloaded methods would automatically be called, even if the type of the pointer is Person, because the actual object pointed to at runtime is a Male (as the compiler has filled in the v-table with a Male object and it's methods).
There are other solutions involving static and dynamic casts, but these only really work if the classes are already polymorphic which yours are not (although, again, they WOULD be if you used virtual functions as I discuss above).
It would be nice to have a little more certainty that the class is really a Male - we are using the fact that we know of a Male's name here, which is good enough for a small program. For a larger program, we would want greater certainty that we don't try to call a method on a Person or Female, when we wanted a Male. But using virtual functions (polymorphism) will at least lead to a graceful execution of the program.
Another comment: It might be better to have a Male class declare as a member, a list of the actual Person *'s for the wives:
eg. declare vector <Person *> wives;
And make sure each Person knows it's name as a string.
Your code will be more efficient if you do this as you could then iterate
over the wives and displayChildren for each wife. And each wife could in turn have a member vector <Person *> children;
I think just using the string vectors is a little cumbersome, as it lacks information. It's not wrong, it's efficient, storage-wise to do it your way.
I realize this means some re-writing of the program but if you don't do this, you will always be iterating over a long Person loop, and trying to find the Person *. You can simply have those Person *'s right in the object of the Male, ready to go right away. I guess it's simpler to have a list of Person's but perhaps it takes a bit more memory?
It's not a BAD idea to store "tree-like" information in an array since traversals of the trees can be put into an array - traversals such as inorder, postorder, and preorder.
Lastly, be careful of your strings for Abraham, Isaac (not Issac), Hagar (not Hager), etc.. This will cause errors if they are not exactly the same throughout the program.