What is the right way to implement Item 20 in "Effective C++"?

Item 20 :  Avoid data members in the public interface

Providing read access to private data seems
straight forward. In the example below, I
just prepend P to the data item in the private
section and then use a function to return
the value.

But, what if I want to provide write access?
Scott's recommendation seems to be:
     Set_val( int value ) { Pval = value : } ;

But, this means that instead of val = 5,
I have to write Set_val ( 5 ) ;

Which frankly does not seem like a step in the
right direction.

How would you provide write access to Pval
in the example below?


Class A {
  int Pval ;
  int val() { return Pval ; } ;
Who is Participating?
nietodConnect With a Mentor Commented:
>> Item 20 :  Avoid data members in the public interface
I assume this is from one of Scott Meyer's book.  

They are great books and many of the points in them must be followed without exceptions, others are simply good suggestions.  Others, somewhere in between.  

Avoiding access to public data members is in-between.  If there are data members whose values are ritical to the safe execution of the class, like say a pointer to something, or a critical of some number of somethings, then it is wise to make this data member private.  This prevents nonmember code from messinpg up this critical member.  And if the member does get messed up, you don't have as much code to search for the culprit.   But some data members may not be so critical.  You might have data members that can freely be changed without disasterious side affects and that will need to be changed by non-member code, like you might have a traffic light class that stores the current color.  It may be reasonable to make that color publci so it can easily be changed and tested.  Now you do need to consider these choices carefully.  If there is a chance that the implimentation may change in regard to a data member, or that work may need to be done whenever the data member is accesssed (like updating other data members when it changes) then you shoudl make it private and provide access functions.  (Because is changes are made the access function is the only code that has to change or if additional work need to be done, the access function can be made to do so.)

If you do decide that a data member needs to be protected and have access functions, then a GetXXX()/SetXXXX() pair of functions is the common choice.  The SetXXXX() function sets the member to the new value and the GetXXXX() function returns the current value.  If the class is changed, these functions can often be changed so that the existing code can continue to use them.  

One alternative is to use a single access function that returns a non-constant reference to the data member, like

int &GetVal() { return PVal; };

This single function can be used to get OR set the data member.  i.e.

Obj.GetVal() = Obj.GetVal() + 12;

Both obtains a value and sets it with the same function.   If the class changes its implimentation, This function can often be changed as well so that existing continues to work.  In the worst case this would usually involve writting a proxy class that is returned by the new form of the function.  The proxy class would then detect the change and update the original class.   Not very pretty.  So this design has questionable values, but it is worth considering.
class A
  int pVal;
  int Val {return pVal};

class B : public A
   friend class C;

class C
    void FunctionThatCanAccess_A_private_vars(A * pClassA)
 B * pClassB = (B*)pClassA;
 pClassB->pVal = -777;

Not the best way to access protected members but can help if you do not have sources for original code.

Seems this is not the answer to your question...

the other way is to provide operator=

class A
operator= (int nValue) {pVal = nValue;};

this can help if you have only one protected member function

Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

>> I have to write Set_val ( 5 ) ;
>> Which frankly does not seem like a step in the
>> right direction.
Is there a particular reason you don't like that?  If you are worried about efficiency, you can make the function inline, there is an excelent chance optimizer will end up producing the same code that woudl occur if you simply set the data member.
i'm repeating what allready was siad
what you should do is to take Scott's recommendation but instead of Set_Val
write operator=

then you"ll have a function like Set_Val
and you"ll call it by the operator = as you wanted
But what if you have two int data members in a class?  how do you set them both with operator =?  
You don't...the get()/set() method is probably the least confusing implementation to shoot for, so I agree with you nietod.
klopterAuthor Commented:
My take on all this is that if I want
a variable which can easily (by easy I
mean using the assignment operator =)
by read and written and I don't
expect that variable to be consistent
with other data in the class (or as
nietod says "is not critical ..."), I should
just make that variable public.  

If I decide that a variable needs to
be protected, I should use get_X and set_X

Overloading = only works for one
variable in the class.  

The upshot is that I am going to
make most variables public because
I am comfortable with that.  Knowing
that I am violating a Scott Myers' law.

Someday, I will revisit this.

i still don't agree with you
you shouldn't make them public

what problrm do you have with the operator=???

second if you have a variable in public you can use '=' instead of the set_func
nothing will stop you 'cause the variable is public

that is all the idea of the private you can make a variable private and with the operator = you can make it look like it public

when you write class's you should be consistent with other data in c++

about operator = that will update more then one variable you can make
and then you can updata all the class variables
As long as everyone and their mother is giving input on this issue, I thought I'd throw in mine. I am a very big fan of hiding data members behind private walls, and then just giving interfaces to modify them. My big reason for this is because I love to alter my data structures, when I think of a better way of doing things, etc. and I like being able to hide those changes from the world, making it alot easier to change data structures.

I also think that operator overloading alot of the time just adds confusion rather than clearing things up...like when I'm operating on my class Pizza, what does + do? Does it increase pizza size, toppings, # of pizzas??

Have a great weekend,
as you know you overload operators only if there is a logic in it <a logic that every one can understand not only you>

like in string class you guest what operator + do it somthing that every programer will guest
but it hard to guest what will do operator -
>> I should just make that variable public.  
Yes but only after careful consideration.  This is clearly a violation of encapsulation, which most OOP programmers would consider an undeniable mistake.  On the other hand, this is what we always did before OOP so it can't be that bad.   The answer lies in knowing advantages of enapsulation and employing it wereever there is or even might be an advantage.  Where there is no advantage, its your call.

>> i still don't agree with you
>> you shouldn't make them public
Why?  You can probably give 100s of cases where it would be bad to do so, but can you say for every case?  Not really.

>> that is all the idea of the private you can make a
>> variable private and with the operator = you can
>> make it look like it public
and why is it advantageous to do that?  You haven't restricted access to the data member.   The only case you could make in favor of this is that if the implimentation was changeed so that data member was changed in type or removed or something, then the operator = might be able to still work.  That is a reasonable point, but sometimes it just not worth the trouble for data members you are extremely conifdent of....
you see the only thing i want to say is if he want to controll the access to pval it should be private not public
if it public you got full controll allways
klopterAuthor Commented:
The upshot is that I know that I am
violating encapsulation by making just about
everything public.  I have decided that
encapsulation is one aspect of C++/OOP
that I am going to ignore for now in favor
of getting my work done.  

My boss is already on my case for spending
too much time learning C++ and not enough
writing code.  

On my next project I will try to focus on encapsulation.  

as you wish and i hope we helped you
>>  if he want to controll the access to
>> pval it should be private not
>> public

klopter, This probably wouldn't help you get things done in the shortrun, but what I did is to write a code pre-processor program that looks at my class definitions and looks for data members that are supposed to have Get/Set functions (it figures this out via comments on the data members). and ths program then writes the Get/Set() functions and inserts them in the code.  its a nice time saver.  Does lots of other things too, like finds the member functions that are defined outside of the class and creates the declarations for them inside the class.  

You may want to consider that for the future.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.