Why are member functions allowed to access private data members of aclass?

  • Thread starter Dwight Army of Champions
  • Start date
D

Dwight Army of Champions

I know that no outside functions can directly acces private data
members of a class, and that all interface should be done through the
get and set accessor/mutator functions, but my question is: What are
class member functions allowed to access their own private data
members? Because of these, data members can be manipulated and changed
without use of the accessors and mutators, and couldn't such behavior
wreak havoc on programs? Why not force the class member functions to
also only use accessors and mutators? That way, if there was a
problem, then the programmer KNOWS that the issue is with the get and
set functions and not anywhere else.
 
D

Dwight Army of Champions

Yes I know they are, and they should be the only member functions that
can access the pivate data members. There should be some special
designation that identifies them as not just member functions but also
special member functions.
 
D

Dwight Army of Champions

I mean, as it is now you have a set_value() function that sets the
value of one of your data members. But there could potentially be
another member function out there of the same class that also sets
this value (by using the this pointer and the assignment operator).
Shouldn't this be disallowed?
 
I

Ian Collins

On 06/28/10 08:29 AM, Dwight Army of Champions wrote:

[please don't top-post]
> Yes I know they are, and they should be the only member functions that
> can access the pivate data members. There should be some special
> designation that identifies them as not just member functions but also
> special member functions.

Why? Aren't all (or at least most) member functions mutators?
 
B

Bo Persson

Dwight said:
I mean, as it is now you have a set_value() function that sets the
value of one of your data members. But there could potentially be
another member function out there of the same class that also sets
this value (by using the this pointer and the assignment operator).
Shouldn't this be disallowed?

That would be enforcing a single paradigm, which C++ generally doesn't
do. You are allowed to use set-functions, but not required.

The class is protected from external manipulation, but the class
members are part of the class, and supposed to know what they are
doing.

A lot of classes do not have a single set_value member, so it
obviously works well anyway.


Bo Persson
 
I

Ian Collins

I mean, as it is now you have a set_value() function that sets the
value of one of your data members. But there could potentially be
another member function out there of the same class that also sets
this value (by using the this pointer and the assignment operator).
Shouldn't this be disallowed?

Setters and getters are a sign of a bad design. If outside entities can
directly manipulate data members, just make them public.
 
F

Francesco S. Carta

on said:
I know that no outside functions can directly acces private data
members of a class, and that all interface should be done through the
get and set accessor/mutator functions, but my question is: What are
class member functions allowed to access their own private data
members? Because of these, data members can be manipulated and changed
without use of the accessors and mutators, and couldn't such behavior
wreak havoc on programs? Why not force the class member functions to
also only use accessors and mutators? That way, if there was a
problem, then the programmer KNOWS that the issue is with the get and
set functions and not anywhere else.

Further to the replies you already got, if you want to enforce this
behavior in a particular class, you can always encapsulate the data in
another class and only allow access through setters and getters - so
that you can centralize checking and debugging, shall you need to, even
for the very member functions of the class that owns that data (well,
not owning it directly anymore, since you'd be proxy-ing it).
 
Ö

Öö Tiib

Yes I know they are, and they should be the only member functions that
can access the pivate data members. There should be some special
designation that identifies them as not just member functions but also
special member functions.

The fact you say you have "accessor" member functions (getters and
setters) to each data member indicates that you lack proper
encapsulation. Possibly you lack OO design whatsoever. Get rid of all
accessors. The next thing where your logic leads is common antipattern
of DoerAndKnower.
 
R

Roy Smith

Dwight Army of Champions said:
I know that no outside functions can directly acces private data
members of a class, and that all interface should be done through the
get and set accessor/mutator functions, but my question is: What are
class member functions allowed to access their own private data
members? Because of these, data members can be manipulated and changed
without use of the accessors and mutators, and couldn't such behavior
wreak havoc on programs?

Well, yes. But then again, any buggy code which can change the data in
your object can wreak havoc. It's up to the programmer to guarantee
that each mutator enforces the class invariants. You might want to look
up "design by contract" to get some ideas about how some people have
addressed this issue.
Why not force the class member functions to
also only use accessors and mutators? That way, if there was a
problem, then the programmer KNOWS that the issue is with the get and
set functions and not anywhere else.

I can see the attractiveness of isolating the enforcement of invariants
to as small an area in the code as possible. Once you get that code
right, you've got a powerful tool to enforce correctness. The downside
is that in most cases, it would probably make things more complicated.
 
J

James Kanze

On 06/28/10 08:29 AM, Dwight Army of Champions wrote:

[...]
Why? Aren't all (or at least most) member functions mutators?

Depends on the class. In a lot of cases, the only member
function which is a mutator is operator=.

On the other hand, most classes don't have very many setters or
getters, so making them the only means of accessing class
members would make most class members totally inaccessible after
construction. Not very useful.
 
C

Chris Ahlstrom

Ian Collins stopped playing his vuvuzela long enough to say:
Setters and getters are a sign of a bad design. If outside entities can
directly manipulate data members, just make them public.

Nah. You never know when you might want to change the setter/getter to
do things besides just setting/getting. Keep 'em under wraps.
 
J

Jorgen Grahn

I know that no outside functions can directly acces private data
members of a class, and that all interface should be done through the
get and set accessor/mutator functions [...]

Says who? In reality it depends on the problem at hand, the class and
its environment. Stated as a fundamental rule like that, I have to say it
sounds very old-fashioned, and will lead to bad code.

/Jorgen
 
J

Jorgen Grahn

Ian Collins stopped playing his vuvuzela long enough to say:


Nah. You never know when you might want to change the setter/getter to
do things besides just setting/getting. Keep 'em under wraps.

If the calling code is also under your control (as it normally is
unless you're a library writer) then that's no problem. Just change
your class, recompile and clean up the calling code which suddenly
stopped compiling.

I prefer doing that to paying in advance for things which may never
happen.

/Jorgen
 
B

Bo Persson

Chris said:
Ian Collins stopped playing his vuvuzela long enough to say:


Nah. You never know when you might want to change the
setter/getter to do things besides just setting/getting. Keep 'em
under wraps.

Nah. If you design a class (struct) with all public data members, you
already know that the members can be changed independently. Otehrwise
you wouldn't do that.


Bo Persson
 
J

Jeremy

Setters and getters are a sign of a bad design.  If outside entities can
directly manipulate data members, just make them public.


Actually, mutator functions are not any sign of anything. At the very
least they allow you to vary the implementation while having the
interface stay the same. If you made the data members public then any
time you need to change the implementation you need to track down
every place in the code that uses that data member and change that
instance. I would argue that that is a bad design.
 
Ö

Öö Tiib

Actually, mutator functions are not any sign of anything. At the very
least they allow you to vary the implementation while having the
interface stay the same.

You about interface like OP suggested that has separate getters and
setters for all private data members? Internal details have leaked all
over the place for random Joe to manage and now it can stay forever
like that? Who cares if such get/set/hack/grab interface can stay same
forever? It *should* change ASAP.
If you made the data members public then any
time you need to change the implementation you need to track down
every place in the code that uses that data member and change that
instance. I would argue that that is a bad design.

PODs are with everything public. POD is not good design? Go ahead and
argue then? Lets copy-paste something. All public, no getters-setters:

namespace SI
{
struct Prefix
{
enum Id
{
NoPrefix,
Deca, Hecto, Kilo, Mega, Giga, Tera, Peta, Exa,
Zetta, Yotta, Deci, Centi, Milli, Micro, Nano,
Pico, Femto, Atto, Zepto, Yocto, Count
};
Id id;
wchar_t const* name;
wchar_t const* symbol;
int factor;
double multiplier() const { return pow( 10.0, factor ); }
// ...
// few other functions like multiplier()
};

Prefix const prefixes[Prefix::Count] =
{
{ Prefix::NoPrefix, L"", L"", 0 },
{ Prefix::Deca, L"deca-", L"da", 1 },
{ Prefix::Hecto, L"hecto-", L"h", 2 },
{ Prefix::Kilo, L"kilo-", L"k", 3 },
{ Prefix::Mega, L"mega-", L"M", 6 },
{ Prefix::Giga, L"giga-", L"G", 9 },
{ Prefix::Tera, L"tera-", L"T", 12 },
{ Prefix::peta, L"peta-", L"P", 15 },
{ Prefix::Exa, L"exa-", L"E", 18 },
{ Prefix::Zetta, L"zetta-", L"Z", 21 },
{ Prefix::Yotta, L"yotta-", L"Y", 24 },
{ Prefix::Deci, L"deci-", L"d", -1 },
{ Prefix::Centi, L"centi-", L"c", -2 },
{ Prefix::Milli, L"milli-", L"m", -3 },
{ Prefix::Micro, L"micro-", L"ì", -6 },
{ Prefix::Nano, L"nano-", L"n", -9 },
{ Prefix::pico, L"pico-", L"p", -12 },
{ Prefix::Femto, L"femto-", L"f", -15 },
{ Prefix::Atto, L"atto-", L"a", -18 },
{ Prefix::Zepto, L"zepto-", L"z", -21 },
{ Prefix::Yocto, L"yocto-", L"y", -24 }
};
}

Ok. So all about measurement unit prefixes in International System of
Units (SI) defined with 50 lines of code. Now do same with your "good"
getter-setter java design and show it to us.
 
J

Jorgen Grahn

Actually, mutator functions are not any sign of anything. At the very
least they allow you to vary the implementation while having the
interface stay the same. If you made the data members public then any
time you need to change the implementation you need to track down
every place in the code that uses that data member and change that
instance. I would argue that that is a bad design.

"Track down" is misleading, because in 99% of all projects, you know
that the compiler will list the places for you. See my posting
elsewhere in the thread.

/Jorgen
 
R

red floyd

I know that no outside functions can directly acces private data
members of a class, and that all interface should be done through the
get and set accessor/mutator functions [...]

Says who?  In reality it depends on the problem at hand, the class and
its environment. Stated as a fundamental rule like that, I have to say it
sounds very old-fashioned, and will lead to bad code.

Ny guess: Says his (sadly mistaken) instructor, probably.
 
P

Puppet_Sock

Setters and getters are a sign of a bad design.  If outside entities can
directly manipulate data members, just make them public.

Set and Get fcns are a sign of shallow design. It is not
universal that such is bad. Sometimes a shallow design is
the right thing to do.

The thing to do to get the design right is to think of a
class as an exporter of some kind of service. It does
some kind of job for you. Maybe that job is something very
high level, involving a deep and complicated abstraction.
"Behave as a shipping terminal" for example. In such a
case you are unlikely to want get/set fcns, as in that case
it would be extremely likely to be bad design. You want to
have fcns that represent what the "shipping terminal" can
do. Probably things like "receive truckload" or such.

You want to make the solution space match the problem space.

But sometimes the service is way less complicated. It could
be "carry around the coordinates of a point in a graphical
interface" or some such. In such cases a shallow design
*may* be appropriate. Maybe, or maybe not depending on the
context. But if it is appropriate, then get/set *might*
be the way to go.

Get/set also tend to be leaky spots in data hiding. If you
have get/set fcns that give/take an integer, for example,
it is a strong indication that the object has an integer
inside. So there is a strong tendancy to do things like
calculating the integer outside the object instead of
inside. Often that is doing things in the wrong place.
You could imagine the shipping terminal class being short-
circuited by having total cargo stored be calculated outside
the class code. Once again, the context will tell you if
that is important.
Socks
 
J

Juha Nieminen

Dwight Army of Champions said:
I know that no outside functions can directly acces private data
members of a class, and that all interface should be done through the
get and set accessor/mutator functions

That's a gross oversimplification, and in fact the overuse of accessors
can often lead to bad design.

While not always completely possible, and in many cases not completely
necessary, it's nevertheless a good design principle that the public
interface of a class should be as abstract as possible and reveal as
little as possible about its internal implementation details.

Public member variables are usually considered bad design because they
expose internal implementation details to the outside, hence potentially
causing outside code to start *depending* on those implementation details,
making changing those details without breaking existing code harder.

Accessor functions are only *slightly* better than public member variables,
especially if there are many such accessors. Now the outside code will not
depend on the member variables directly, but it will depend on the accessors.
Hence removing, renaming or doing other kinds of changes to these accessors
will probably break existing code. (It's not completely unusual that when
refactoring a class its member variables are redesigned from scratch, hence
often making some of the accessors obsolete or in need of heavy modification
which changes significantly their signature.)

The ideal situation is when the public interface of the class is so
abstract that the outside code depends as little as possible on these
internal implementation details. This makes it much easier to change these
details without having to change the public interface and hence breaking
existing code. (Naturally, as I already said, this is not always completely
possible, but it would nevertheless be the ideal case.)

There are some languages (such as C#) where all public member variables
can be replaced with accessors without any change in syntax in the outside
code. While this might sound handy at first, my personal opinion is that
this kind of language feature is actually a mistake which, rather ironically,
often leads to rigid code which is hard to refactor and modify. That's
because the feature induces programmers to put member variables in the
public interface of classes (thinking "I can always replace them with
accessors if needed, so it doesn't matter"), making outside code depend
on these implementation details, thus making it harder to change these
details later. In other words, this feature often induces people to write
less abstract code, to their own detriment.
but my question is: What are
class member functions allowed to access their own private data
members?

I find that question rather strange. How should they access their own
data then? If your answer is "through accessors", then exactly how do you
implement those accessors? Accessors *are* member functions, after all.
If member functions couldn't access member variables directly, then you
couldn't implement accessors.

(Yes, accessors must be regular member functions. That's the whole idea
of an accessor: That you could modify it to do something completely
different than simply return/set a member variable. Heck, the equivalent
member variable might not actually exist at all.)

From a design point of view, restricting access rights exists to stop
outside code from accessing member variables directly, not to stop inside
code from doing so. Inside code is restricted to a single module and thus
is well encapsulated, making refactoring easier.
Because of these, data members can be manipulated and changed
without use of the accessors and mutators, and couldn't such behavior
wreak havoc on programs?

Why would this be so?
Why not force the class member functions to
also only use accessors and mutators?

And how do you suggest those accessors and mutators be implemented?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top