BaloneyOs
BaloneyOs

Reputation: 317

C++ constructors functionality

So I'm doing a final review sheet for my first semester of C++ (and programming in general) and I came across this problem:

Write a class Person with private members string name, string idNum, in addition to a class Student which inherits from Person with private members string major, int gradYear. Implement the constructors, getters and setters.

I ended up reviewing constructors and decided to watch some YouTube videos to clarify some things and clear up some potential misunderstandings I may have had from class. Now from what I understand, if I were to do this just for the member "name", it should come out looking something like this:

class Person
{
    public:
        Person(string z)
        {
            setName(z);
        }
        void setName(string x)
        {
            name = x;
        }
        string getName()
        {
            return name;
        }
    private:
        string name;
};

(please let me know if I did this correctly to begin with)

Then I looked at some of my professor's examples and in one of them he wrote the following class:

class Shape 
{
    public:
        void setPosition(int x, int y) 
            { 
                xpos = x; ypos = y; 
            }
        double getArea() 
            { 
                return 0; 
            }//return length * width; }
    private:
        int xpos, ypos, name;
};

This is where I get confused because if I were to follow this convention, I would not include any setters? Would my answer be functionally the same without the setter, which would then look like this?

Edit: Whoops, the example did have a setter and I must've confused it with the constructor itself unless it's actually both?

class Person
{
    public:
        Person(string z)
        {
            setName(z);
        }
        string getName()
        {
            return name;
        }
    private:
        string name;
};

I'm aware that the question did specifically ask for the getters as well, but I just want to clear some things up because there seems to be some conflicting information.

Upvotes: 1

Views: 132

Answers (3)

Syren Baran
Syren Baran

Reputation: 444

This is not limited to C++, but general OOP style.

Usually you will have both setters and getters, e.g. setFirstName(..) and getFirstName(), since you those are states that can change (especially a lastname via marriage) or simply because not all data was available when creating the object, someone made a typo, whatever.

If you have a derived property you will usually only have a getter. In the above example you have a getArea() method, a setter doesnt really make any sense, whereas a setWidth(..) and setHeight(..) obviously do. Another example would be a getSalutation() (which could return some combination of title, firstname and lastname).

In some cases, e.g. for dependency injection, just having a setter can also be correct.

Sometimes you dont want any accessors at all. This can be the case for internal variables where setting these may cause inconsistencies or even security concerns. Note however, that by hiding those variables (via private scope) you are pretty much assuming you know best how to deal with every use case.

Upvotes: 2

Konrad 'Zegis'
Konrad 'Zegis'

Reputation: 16481

No, yours example without setter would look like this:

class Person
{
    public:
        Person(string z)
        {
            name = z;
        }
        string getName()
        {
            return name;
        }
    private:
        string name;
};

You can't invoke setName as you wrote it in question because setName(String) function isn't defined.

But if you write it that way you couldn't change name for any instance of person. Basically when field inside of object (basic type variable, or another object) is set to private you can't access it from outside of that object. So by writing Person like this you make it immutable - after creation you can't change contents of Person instance.

You can consider it as choice: Either use public variables, or private with setField and getField methods. Basically second option is best, because you can always add some logic to setter - i.e. capitalize letters inside your string, or check if provided value is valid.

In professor's example you've provided there is setter - void setPosition(int,int) method, but he didn't wrote constructor, so compilator'll add default parameterless constructor that won't set xpos, nor ypos.

Upvotes: -1

erip
erip

Reputation: 16935

You can think of constructors as an instantiater that set member attributes. The difference is that constructors get called exactly once for an object. Consider you have a class with a field that will not change - if you write a public setter, this would be incorrect.

Consider the situation of Americans with social security numbers. It is awfully rare to change your SSN, so if you were modeling an American (person), you might not include a set_ssn method.

class American {
  public:
    American(std::string name, std::string ssn) { 
      name_ = name; 
      ssn_ = ssn; 
    }
    void interact() { /* do my living stuff */ }
  private:
    std::string name_;
    std::string ssn_;
};

Now you can use this like so:

American erip("Elijah", "mysecretssn");
erip.interact();
...

If I regularly change my hair color, you could add a set_hair_color method to my class.

void set_hair_color(const std::string hair_color);

and a std::string hair_color_ to my private members.

Now I could do this:

American erip("Elijah", "mysecretssn");
erip.interact();
erip.set_hair_color("black");
erip.set_hair_color("red");
...

In summary, you will write setters if things change about your person, but all member functions have access to private variables and can thereby change them. Setters are a way to "publicize" your member variables to the user of your code.

Upvotes: 3

Related Questions