1

I'm trying to create a simple family tree in C++ by utilizing pointers in order to input strings for names that are then saved step-by-step within the code.

For example, the program starts at an unknown spot, and the user is prompted to either enter a name for the current spot, move to the dad's spot, move to the mom's spot, or go back to the starting person (first person registered). This is what I've got so far:

#include <iostream>
#include <cstdlib>
using namespace std;

class person
{
public:
    person* mom;
    person* dad;
    string name;
    person();
    ~person();
    person(string n);
};


person::person()
{
    mom = nullptr;
    dad = nullptr;
    name = "Unknown";
}    

person::~person()
{
//delete any dynamic memory if needed
}

person::person(string n)
{
    name = n;
}

int main()
{
string inputName;
person current;
person *pointer; //I know I'll probably need to use a class pointer 
//in some manner to keep track of the current pointer, but how?
//also, how to turn private variables in person into public
//while still being able to use them indirectly in main, if possible? 

char choice;
do {
    cout << "You are currently at: " << current.name << endl;
    cout << "Your mom is: ";
    if(current.mom == nullptr)
    {
        cout << "???" << endl;
    }
    else
    {
        cout << current.mom;
    }
    cout << "Your dad is: ";
    if(current.dad == nullptr)
    {
        cout << "???" << endl;
    }
    else
    {
        cout << current.dad;
    }
    cout << "Give name, go to mom, go to dad, back to start, or quit?" << endl;
    cin >> choice;

    if (choice == 'g')
    {
        cout << "What name (single word)?" << endl;
        cin >> inputName;
        current.name = inputName;
    }
    else if (choice == 'm')
    {
    //go to mom spot
    }
    else if (choice == 'd')
    {
    //go to dad spot
    }
    else if (choice == 'b')
    {
    //go to first registered name
    }
}
while (choice == 'g' || choice == 'm' || choice == 'd' || choice == 'b');
//else quit
return 0;
}

My code is quite sloppy at the moment, as I'm a complete beginner to C++ and only started about a week ago on my own. I know public variables are a really bad practice, but I don't really know how to use private variables within main. Any help with how to organize my pointers or how to make private variables work within main would be greatly appreciated.

kiril
  • 11
  • 2
  • 5
  • You are attempting something moderately tricky very early in your learning process. This is the sort of task given as part of an Algorithms and Data structures course taken a semester or two into a computer science course, and usually after the class has been decimated by a linked list assignment. In order to successfully accomplish this task, you need a good grip on a bunch of concepts you do not have. Challenge yourself, but at this point you don't know enough of the fundamentals to attack this problem. – user4581301 Apr 27 '18 at 04:24
  • The best advice I can give is draw pictures to visualize the problem. Illustrate what you want to do on a piece of paper step by step and take very good notes on what you are doing and why. The notes will provide the basis for your code. The next best advice would be to hide 'person` away from `main` by adding another class, `FamilyTree` to manage the tree pf `person`s. `FamilyTree` is a `friend` of `person`, getting around the problem of accessing `private` data. `FamilyTree` contains all of the functions `main` needs to add people to the family tree and navigate it. – user4581301 Apr 27 '18 at 04:30
  • Looks like a question for the codereview.stackexchange.com – JVApen Apr 27 '18 at 06:23

1 Answers1

0

You declared and defined your class' public members correctly, to implement the private ones you do not need to change too much.

Under your class definition, you simply need to include a "private:" section as well. You declare your private variables or functions under there, and the getters and setters for these variables under the public header.

so your

class person
{
public:
    person* mom;
    person* dad;
    string name;
    person();
    ~person();
    person(string n);
};

Becomes

class person
{
public:
    person();
    ~person();
    person(string n);

    void setName(string);

    person* getMom();
    person* getDad();
    string getName();
private:
    person* mom;
    person* dad;
    string name;
};

Note that when declaring a function, you do not need to provide the name of any parameter variables. That is completely optional; the compiler only need know what type of variable to expect.

Then, just like how you defined your constructors and destructor, you define the getters and setters you just declared.

...
person::person(string n)
{
    name = n;
}

void person::setName(string name)
{
    this->name = name;
}

person* person::getMom()
{
    return mom;
}

person* person::getDad()
{
    return dad;
}

string person::getName()
{
    return name;
}

int main()
...

This formatting is essentially the same as if you were to separate the Person class into its own header (.h) and cpp (.cpp) files.

Then, to access your private members you need only call the getters or setters you just created. So,

cout << "You are currently at: " << current.name << endl;

Becomes

cout << "You are currently at: " << current.getName() << endl;

Hope that makes sense.

ps: If you're using C++'s string class you may want to #include <string>

pps: Its good practice to always capitalize the first letter of whatever class you are making. Just so it stands out. Person instead of person.

  • A decent start, but ask yourself what advantages do the accessor functions give you over `public` members? A public accessor that allows the caller to modify a member in any way the caller sees fit is not much better than a `public` variable. All it adds is a place to hand a debugger breakpoint to find out who is setting bad values. A good accessor provides defence for the object, restricting the caller's access in some way or at the very least monitoring the change so that the object can maintain a consistent state. – user4581301 Apr 27 '18 at 04:16
  • string person::getName() will return a copy of the string name, won't it? – Chris Hansen Apr 27 '18 at 04:43
  • Yes it will. And I don't really have a problem with `setName`. Where this gets ugly is with stuff like a `setMom` method where casual mis-use is fatal to the program. Any fool can break the tree. You've left it out of the class, but unless you explain why you left it out, my money is on the asker adding, using, and regretting it. – user4581301 Apr 27 '18 at 04:52