Hello!
I'm relatively new to C++ and I'm learning about classes and objects. I've learned most of what I know from YouTube tutorials and some books. Well, in almost all of those, they mentioned that it was poor programming practice to make all your data members public, inside of a class. If they are all private, how may I access it from different functions? I think I have a general idea of how to go about doing this, and I will post below. Please correct me if I am wrong.

#include <iostream>

class testClass {
private:
int i;
public:
int testFunct(int i){
int i=42;
cout<<i<<endl;
}
};

int main() {
testClass testObj
testObj.testFunct;
}

Basically, what I think the concept is, is to make all your variable definitions in the private section of the class, and then give them values and use them in the public section? The you can pull it straight from the public when you need to use it?
Thanks for any help, and also there may be some errors in the code above :P
Carpetfizz

You use setter and getter methods:

class testClass 
{
    private:
        int value;

    public:
        int GetValue()
        {
            return value;
        }
        int SetValue(int v)
        {
            value = v;
        }
};

This way the class has total control of the data for safety, but other functions can still access the value.

Edited 4 Years Ago by WaltP

Welcome!

I've learned most of what I know from YouTube tutorials and some books.

Ditch the youtube tutorials, and make sure your book(s) is good. People who took the time to write a good quality book usually took the time to make their explanations clear and their approach suitable for the learner. People who put together a youtube video tutorial in an hour of spare time usually didn't.

Well, in almost all of those, they mentioned that it was poor programming practice to make all your data members public, inside of a class.

Roughly speaking, that's true. But, of course, as most "rules" in programming, they aren't black-and-white, it's the reasoning behind it that is important, and I think that is exactly what brought you here, so I'm glad for that.

If they are all private, how may I access it from different functions?

Well. That's the point of it all. The private/public/protected are access right specifiers and their purpose is to control from where the members can be accessed. When you create a class, all the data members and member functions of the class can be accessed by any parts of the implementation of that class. When you mark data members or member functions of a class as being private, you make it so that they are only accessible through parts of the implementation of that class, but not anywhere else. When you mark them as public, they are accessible from anywhere.

Here is a simple example:

#include <iostream>
using namespace std;

// I declare a class:
class FooPublic {
  public:
    int bar;  // declare a public data member.

    int getBar();  // declare a public member function.
};

// I declare a second class:
class FooPrivate {
  private:
    int bar;  // declare a private data member.
  public:
    int getBar();  // declare a public member function.
};

// Now, I implement the function for FooPublic:
int FooPublic::getBar() {
  return bar;            // the data member 'bar' can be accessed here.
};

// I implement the function for FooPrivate:
int FooPrivate::getBar() {
  return bar;            // the data member 'bar' can be accessed here.
};

// Now, I start the 'main' program:
int main() {

  FooPublic f1;  // create an object of type FooPublic.

  int v1 = f1.getBar();  // the public function is accessible from here.

  int v2 = f1.bar;  // the public data member is accessible from here.

  FooPrivate f2;  // create an object of type FooPrivate.

  int v3 = f2.getBar();  // the public function is accessible from here.

  int v4 = f2.bar;  // ERROR: the private data member is NOT accessible from here.

  return 0;
};

This last statement int v4 = f2.bar; is an error because the function main() is not part of the implementation of the class FooPrivate and thus, it has no right to access the private members of that class. This is basically the point of this whole thing. If you want to control the access to your data members (like a gate-keeper), you must make them private (or protected, but you'll learn that later on), because, otherwise, you cannot control the access to them.

This can be useful in situation such as those where the different data members are related somehow and must have consistent values, i.e., when you change one value, you must update the value of another data member(s) accordingly. If you want to do that, you must make a public function through which the data members can be updated, but you must also forbid people from tempering with the data members directly.

In some trivial cases, it is not necessary to do this, but it's a good habit to have, especially as you learn.

Basically, what I think the concept is, is to make all your variable definitions in the private section of the class, and then give them values and use them in the public section?

Not exactly. Think of it like this. The things in the public section define how your class is to be used. The things in the private section define how your class does its job. The data and functions that the class needs to be able to perform the tasks that users of the class will ask it to perform is what goes into the private (or protected) section, while the public section is purely for "how you want people to use your class".

Take the example of a "stack" class. A stack is basically just a pile of objects, all you do with a stack is put objects on top of what's already there (this is called "pushing") and taking the top object off of the stack (this is called "popping"). So, without much surprise, the standard std::stack class has 5 public functions: push, pop, top (read the value of the top element), size and empty (check if empty). It doesn't need any more functions than that, because if you needed to do any kind of tasks that were more complicated than that, you wouldn't be using this class (you'd find some other class that suits your needs better). But I can guarantee that "under-the-hood", i.e., in the private section of that class, there are a lot more things that you can't access (data members and functions) that only the stack class can access.

Long story short: "if the user doesn't need to see it, then it should be hidden".

Thanks for any help, and also there may be some errors in the code above :P

There are a few errors in the code you posted. I highly suggest that you get very familiar with your compiler if you want to learn to program. Always test your code, and compile code frequently. Make lots of test programs, make sure to compile and run them. When in doubt about what works and what doesn't, or what a certain piece of code will output, just test it out, it's the simplest and quickest way to find out. This is what professionals do too. Try to compile the code you have, and then, try to resolve the errors by yourself, read the error messages carefully. Also, you should always compile with highest warning levels (check you compiler options for how to set that up).

Thank you very much for both of your advice, I think I understand this now! Also @mike, I know there are errors in the code, and of course it wouldn't compile, just wanted to create a rough code of what my thinking was. Now, I know that I was wrong, and understand how to make this work correctly. As for the compiler, I've been using Code Blocks, because I'm not at my normal location and lacked internet bandwidth for VS.
EDIT: Mike, I was going through your code and I understand most of it, but just want to clarify a few things for the sake of my learning. On line 7 and on line 15 you define "bar" but on one it is public and on one it is private. What is the point of doing this, and how does it help in hiding code since "bar" is in the public section of the class at first?

Edited 4 Years Ago by Carpetfizz

EDIT: Sorry for the double post, the edit on my first reply didn't show up for some reason, so I typed it out again.
@Mike, I understook most of your code, but I wanted to clarify a couple things.On lines 7 and 15 you define "bar", what exactly is the point of doing this when one of them is already public? Thanks again.

Edited 4 Years Ago by Carpetfizz

I understook most of your code, but I wanted to clarify a couple things.On lines 7 and 15 you define "bar", what exactly is the point of doing this when one of them is already public? Thanks again.

Well, my code was just an example for you to understand the difference in where you can access public or private members. And, line 7 and line 15 have nothing to do with each other except that the name of the data member is the same. At line 7, I declare a public data member called "bar" which is a data member of the class called "FooPublic". On line 15, I declare a private data member called "bar" which is a data member of the class called "FooPrivate". These are two separate classes, each with their own data member called "bar". So, it doesn't make any difference that "one of them is already public", the thing is one is a public data member and the other is a private data member, but they are separate data members belonging to separate classes.

Ah thanks much, this definitely cleared it up for me! Now, I understand all of it, but back to my original question, how do I access "bar" from something like line 43, because we were only able to retrieve the variable from the public function, and you could do that anyway? Am I overthinking this lol?

Edited 4 Years Ago by Carpetfizz

how do I access "bar" from something like line 43

You can't.

because we were only able to retrieve the variable from the public function, and you could do that anyway?

Yes, but the important thing is that you can only access it through the public function. This is especially important when you are setting the value of it. Imagine you have this class:

class Vector2D {
  private:
    double x;
    double y;
    double magnitude;
  public:
    double getX();
    double getY();
    void setX(double newX);
    void setY(double newY);
    double getMagnitude();
};

Now, at all times, you want the data member "magnitude" to reflect the magnitude of the vector, so, anytime you update the values of x or y, you need to recalculate the magnitude. If you allowed access to x or y directly, you wouldn't be able to do that, but by controlling the access to x and y through these public functions, you can do the following:

double Vector2D::getX() {
  return x;
};

double Vector2D::getY() {
  return y;
};

void Vector2D::setX(double newX) {
  x = newX;
  magnitude = sqrt( x * x + y * y );
};

void Vector2D::setY(double newY) {
  y = newY;
  magnitude = sqrt( x * x + y * y );
};

double Vector2D::getMagnitude() {
  return magnitude;
};

See how I can easily make sure that the value of "magnitude" is always consistent with the values stored in x and y, because anytime the user wants to modify those values, he has to go through the functions "setX" and "setY".

Comments
Excellent explanation of why we use setter methods instead of allowing direct access to member variables.

Private: This is only stuff that I can access directly or change.
Protected: This is only stuff that I, or my children (derived classes) can directly access or change.
Public: This is what I let the world access.

Then, we have "friends". Our friends can access/change private and protected elements that we have allowed them to. IE, I can allow a friend to come into my house and get beer out of the fridge, but not drive off in my car... :-)

Comments
why the downvotes? i think his analogy is pretty helpful...

Thank you very much for the comprehensive clarification Mike, and thanks rubberman as well for the definition. I definitely understand this concept a lot more than I did a couple days ago, and will practice it to really get it in my head. Also learned a thing or two about vectors :)

Edited 4 Years Ago by Carpetfizz

This article has been dead for over six months. Start a new discussion instead.