Why make class members private?

2020-02-29 04:27发布

问题:

I've learn C++ for some time, however there is always this question which puzzles me (for years). In school, our lecturers like to declare class variables as private. In order to access it, we have to declare an accessor to access it.

Sometimes we even have to make the different classes become "friends" into order to access its elements.

My question is: Why make it so troublesome? What is the true rationale behind all the private and protected stuff when we can just make our life as a programmer easier by using public for everything?

I was thinking, once the code gets compiled, the end user will not even differentiate whether we use public or private in the back end coding, so why still need to declare it properly as private, protected...etc ?

回答1:

To make your code easier to understand and maintain.

When you make a data member public, other programmers who use your class will naturally tend to use these public members rather than some member function that provides similar or the same information simply because it's easier. You might even tend to do this yourself. That's understandable -- programmers are inherently lazy beasts.

But suppose you realize somewhere down the line that the information that member function provides can no longer be generated from just that one member variable. Worse, what if that member variable becomes obsolete in the face of a design change. Worse still, what if the member variable itself isn't removed, but the semantics of it change.

Let;s consider an example. Say you have a class which represents items you have for sale:

class Gizmo
{
public:
  std::string mSku;
};

That's it, all you have is a sku. Suppose the contents of mSku are simply the product number, something like "12345".

You finish your code, ship it, and life's great. Until your company becomes as successful as Amazon, and now you start getting the same product from multiple vendors. You decide that the best thing to do is to encode the mSku so that it contains vendor information along with the produce number. The same widget from two different vendors might have very different skus: S:12345, Z:12345.

Any code that was written that expects mSku to be just a product number is now broken, and it will all have to be re-factored. In this silly little example it could be a problem. Imagine a codebase of 1 million lines of code -- not uncommon at all. You and all your coworkers have probably forgotten all about all the places where mSku is being used. None of the code will fail to compile, so the compiler's no help -- but all of that code is broken. This is a huge problem.

It would have been better at the outset if you hadn't relied on mSku at all, but provided a member function which was contracted to return the product number. Something like:

class Sku
{
public:
  std::string ProductNumber() const;
private: 
  std::string mSku;
};

Now you can change the semantics of mSku all you want. So long as you refactor what ProductNumber() does to return the product number, all those 1 million lines of code will still compile and still be correct.

In fact, I generally take this one step further. I will generally make everything in a class private until there is a specific reason to make it something else. Even then, I'll only make it protected unless I actually need it to be public.

[Why can't we] just make our life as a programmer easier by using public for everything?

In a large codebase, even if it's only maintained by one person, you actually make your life easier in the long run by making a lot of this stuff private from the very start.



回答2:

You mark class members private: to reduce the number of things on which other developers who use your code may depend. The moment that you release your code for use by somebody else, everything that he can use becomes your maintenance liability. You cannot simply remove a public member function, or change its argument types, because doing so would break someone else's code.

That is why it makes sense to shrink the number of items that you must preserve, to give yourself more flexibility at changing implementation of your class. If a member is private, you are free to change or remove it without causing problems to other people who use your code. This is essential when you develop code in a team.



回答3:

See C++ standard 11.1.

There is a philosophy behind object oriented design in c++.

Objects exist to provide portable functionality to the rest of your code. In order to make this possible, you should be able to specify how your objects are to be used by the next coder (even if the next coder is you).

In order to maintain that your object is strictly defined in the code for that class, it should present an interface to it's functionality. Usually this is just getters and setters. These are written so that in case you need to change how members are accessed, this is done in your class and no where else. To ensure this is the case, your member objects need to be private.