data members as "protected"?

J

JKop

Act posted:
Why is it suggested to not define data members as "protected"?

Thanks for help!

Why is it suggested to not walk around alone at night?

Thanks for help!


-JKop
 
M

Mike Wahler

Act said:
Why is it suggested to not define data members as "protected"?

IMO that's too general an advice to be meaningful. From
where did you get this suggestion?

Specifying a member (data or function) as 'protected'
means that derived classes have direct access to them.
Use 'protected' if that's what you need.

-Mike
 
D

Daniel T.

Act said:
Why is it suggested to not define data members as "protected"?

The assumption is that the member data was put in this particular class
because there was some invariant that has to be maintained and this
class is the one designated to maintain it.

Obviously, given the case above, the class can't ensure the invariant if
it can't control access to the data.

What if the assumption doesn't hold? In that case, you might as well
make the data public.
 
W

White Wolf

Act said:
Why is it suggested to not define data members as "protected"?

Because derived classes depending on it will be too dependent on their
bases. Why is that a problem? Because if youy want/need to change your
base class design you cannot. Because derived class (you may not even know
about) depend on those protected members to be there and not to change. And
experience shows that data members do change.
 
D

David Hilsee

Act said:
Why is it suggested to not define data members as "protected"?

Some suggest that, some don't. I generally avoid protected data members,
but some people don't mind. For instance, the answers in the FAQ
(http://www.parashift.com/c++-faq-lite/) under "Inheritance — basics",
questions 8 and 9 lean towards protected data. I must admit that the
paragraph deriding "purists" is a bit, er, melodramatic.
 
C

Cy Edmunds

David Hilsee said:
Some suggest that, some don't. I generally avoid protected data members,
but some people don't mind. For instance, the answers in the FAQ
(http://www.parashift.com/c++-faq-lite/) under "Inheritance - basics",
questions 8 and 9 lean towards protected data.

"Lean"? hehe
I must admit that the
paragraph deriding "purists" is a bit, er, melodramatic.

My take on this is that whenever you use the keyword "protected" you are
expecting your client to derive from the class. In such a case I don't see
why protected data is any better than public data -- either way you are
giving your client full access to your implementation details. The FAQ makes
a big distinction between cases where you expect the client to be "on your
team" or not. Even if I could be sure my client is on my team I don't see
how that makes bad software design practices suddenly desirable. Would you
use public data if you thought your client was on your team? I hope not.

The FAQ also mentions the dubious practice of replacing protected data with
protected get/set methods. I agree, but I don't think public get/set methods
are so hot either.
 
A

Alf P. Steinbach

* Cy Edmunds:
"Lean"? hehe


My take on this is that whenever you use the keyword "protected" you are
expecting your client to derive from the class. In such a case I don't see
why protected data is any better than public data -- either way you are
giving your client full access to your implementation details.

A derived class (on the one hand) and so-called client code (on the other
hand) are two different kinds of client.

A derived class is a fully trusted client: you're giving it access to your
innards, and if it screws up then you (or it) is dead anyway.

So-called client code is a non-trusted client: you're doing your utmost to
ensure that nothing client code can do while _adhering_ to the stated
contracts can screw up anything. But on the gripping hand it's futile to
try to protect against intentional misdeeds. Anyone can reinterpret_cast,
and/or make their own modified class declaration, or whatever, so the
protection levels should be assigned with that in mind: you're not protecting
agains intentional hacking and misdeeds, but against accidental blunders, and
the care you can and must assume in the client depends on the kind of client.


The FAQ makes
a big distinction between cases where you expect the client to be "on your
team" or not.

A good point, but "on your team", if that's the expression the FAQ uses, is
a bit misleading.

It should be more like "part of your body"... ;-)

But these times even that is perhaps not strong enough: a derived class is
a very, Very, VERY intimate & strong relationship.
 
A

Alf P. Steinbach

* John Brown:
Stroustrup for one (referring to protected data in particular). See section
15.3.1.1 in http://www.research.att.com/~bs/3rd.html

Perhaps you would kindly quote the passage instead of giving a reference
that doesn't contain or give further reference to the passage.

I once had the 3rd edition but now am left with only 1st and 2nd editions.

Anyway it's not our job to do the work in making your argument: DIY.
 
D

David Hilsee

A good point, but "on your team", if that's the expression the FAQ uses, is
a bit misleading.

It should be more like "part of your body"... ;-)

I'm not sure what you mean by "part of your body". The FAQ was basically
arguing that derived classes tend to be limited in number and maintained by
your team, so a base class change that causes the derived classes to change
will not cause much grief.
But these times even that is perhaps not strong enough: a derived class is
a very, Very, VERY intimate & strong relationship.

A derived class's relationship with its base is only as intimate as the base
allows it to be. For example, a class that derives from std::vector has no
stronger relationship than any other client. If the base exposes a lot in
its "protected interface", then yes, the derived class may have to be
updated if the base class changes. However, this is not required by any
means.
 
A

Alf P. Steinbach

* David Hilsee:
I'm not sure what you mean by "part of your body". The FAQ was basically
arguing that derived classes tend to be limited in number and maintained by
your team, so a base class change that causes the derived classes to change
will not cause much grief.


A derived class's relationship with its base is only as intimate as the base
allows it to be.

True but irrelevant: when you design for inheritance you're aiming for the
very Very VERY intimate relationship, not the armored warfare relationship;
and there's basically nothing in-between the these points, for any brink in
the armor gives the first kind automatically.

For example, a class that derives from std::vector has no stronger
relationship than any other client.

I don't care to check that for accuracy, but again: even if true it's
irrelevant. You might want to check out std::list for a counter-example.

If the base exposes a lot in
its "protected interface", then yes, the derived class may have to be
updated if the base class changes.

Replace "a lot" with "anything", and tack onto the end, "in the protected
interface"... ;-)

In other words, that statement is misleading in two ways.

A more general & correct statement: if a base class is changed, then any
derived class may have to be updated. And the consequence is that the
cost of design, the cost of updates, the cost of deriving and using, the
cost of (in)efficiency, and so on, must be balanced. That's an engineering
decision requiring sound judgement: it should not, IMO, be made using
cookbook recipe rules like "don't use protected for data members".

However, this is not required by any means.

Right, but see above.
 
D

David Hilsee

Alf P. Steinbach said:
* John Brown:

Perhaps you would kindly quote the passage instead of giving a reference
that doesn't contain or give further reference to the passage.

It's about 4 paragraphs long. I don't want to quote the whole thing, but in
my copy of special edition, it says things like "declaring data members
protected is usually a design error", "protected data becomes a software
maintenance problem", and "none of these objections are significant for
protected member functions; protected is a fine way of specifying operations
for use in derived classes".
 
D

David Hilsee

Alf P. Steinbach said:
* David Hilsee:

True but irrelevant: when you design for inheritance you're aiming for the
very Very VERY intimate relationship, not the armored warfare relationship;
and there's basically nothing in-between the these points, for any brink in
the armor gives the first kind automatically.

Well, _you_ may aim for a very intimate relationship. I was pointing out
that an intimate relationship can be avoided. IMHO, the usage of an extra
exposed detail or two in the protected interface does not automatically
constitute a "very very VERY intimate relationship". It's more intimate
than others who are restricted to the public interface, that's for sure.
I'd argue that there is certainly an area in between "armored warfare" and
"extremely intimate".
I don't care to check that for accuracy, but again: even if true it's
irrelevant. You might want to check out std::list for a counter-example.

How is std::list a counterexample? It has no standard protected members.
Replace "a lot" with "anything", and tack onto the end, "in the protected
interface"... ;-)

In other words, that statement is misleading in two ways.

A more general & correct statement: if a base class is changed, then any
derived class may have to be updated. And the consequence is that the
cost of design, the cost of updates, the cost of deriving and using, the
cost of (in)efficiency, and so on, must be balanced. That's an engineering
decision requiring sound judgement: it should not, IMO, be made using
cookbook recipe rules like "don't use protected for data members".

Oh, sure, the FAQ argues this too: one size does not fit all.
 
A

Alf P. Steinbach

* David Hilsee:
Well, _you_ may aim for a very intimate relationship. I was pointing out
that an intimate relationship can be avoided. IMHO, the usage of an extra
exposed detail or two in the protected interface does not automatically
constitute a "very very VERY intimate relationship". It's more intimate
than others who are restricted to the public interface, that's for sure.
I'd argue that there is certainly an area in between "armored warfare" and
"extremely intimate".

Okay, we'll have to agree to disagree here. Except that I agree that the
I-word relationship can be avoided -- but IMO at very high cost. So!

How is std::list a counterexample? It has no standard protected members.

Bugger this keyboard. It doesn't write what I mean. Three examples of
standard containers with protected data members are std::queue, std::stack
and std::priority_queue (this time I checked it out, hope this helps).
 
D

David Hilsee

members.

Bugger this keyboard. It doesn't write what I mean. Three examples of
standard containers with protected data members are std::queue, std::stack
and std::priority_queue (this time I checked it out, hope this helps).

I realize that there exist classes within the standard library that expose
protected members. I wasn't trying to say that any inheritance relationship
established with a standard class is as intimate as one with any other
standard class. I was just pointing out that a class can limit the
interface it exposes to the derived class so much that its relationship is
the same as any other client, if that is what the programmer desires. Of
course, I picked std::vector as an extreme case because it's not really
designed for inheritance at all.
 
C

Cy Edmunds

[snip]
A derived class (on the one hand) and so-called client code (on the other
hand) are two different kinds of client.

A derived class is a fully trusted client: you're giving it access to your
innards, and if it screws up then you (or it) is dead anyway.

A "trusted client"? That's where we disagree. Sure, over the next few months
you and your teammates will probably all be there and understandings and
agreements you have in place will work OK. But as time goes by people come
and go. If your code is to still be maintainable with a new set of players
my advice is: don't trust anybody!

Obviously, if there are pressing issues of performance or whatever that
demand protected data you do what you gotta do. Otherwise, IMHO it's just
plain sloppy programming.

[snip]
But these times even that is perhaps not strong enough: a derived class is
a very, Very, VERY intimate & strong relationship.

I see no reason why it need be any more intimate than a public interface.
 
H

Howard

... But on the gripping hand ...

Cool! You know, I've never heard anyone else ever mention that term before.
I thought that maybe I was the only one to ever read that book! :)

-Howard
 
H

Howard

Cy Edmunds said:
The FAQ also mentions the dubious practice of replacing protected data with
protected get/set methods. I agree, but I don't think public get/set methods
are so hot either.

You agree with a "dubious practice"? That's a strange thing to say... (Or
did you mean you agree that it's a dubious practice? If so, why?)

In any case, you either have to have get/set methods, or you have to expose
the data itself, right? I'm confused which it is that you prefer...?

For me, I tend to use public data for POD structs (e.g., something simple
like a three-d vector with .x, .y and .z members), but I prefer private data
for my more complex classes. However, I do use protected data in some
instances, because I'm generally writing all the classes involved, base and
derived, and it's simply quicker to leave the data as protected and directly
access the members instead of writing a bunch of getters/setters. (There
are also performance issues involved in a few cases, but most of those
involve me deriving from a third-party class that's already made the design
decisions for me.)

As for the visibility of the get/set methods, whether they're protected or
public really depends upon whether I want external code to read or write to
those (perhaps with some kind of checks/asserts/side-effects, etc.), or if
only the derived classes need to read and/or modify those values. If only
derived classes need to know about these "details", the protected
gettters/setters make sense, right? But if they're required information for
the world in general (like the Name of a Person), then surely public
getters/setters are *required*! I mean, if the data itself isn't public,
then what other method of access is there?

In summary, my take on this is that, well, it all depends! No hard-and-fast
rule is likely to apply to all the needs of all the programmers all the
time. We're paid (well, in general), to make intelligent decisions, and we
ought to be able to justify a given decision by thinking it through in the
first place. So if your boss asks "why is this data private instead of
protected", you shouldn't be answering "because protected data is bad", but
rather you should explain why you made the decision in that particular case.

-Howard

"Rule #1: There are exceptions to every rule."
 
C

Cy Edmunds

Howard said:
You agree with a "dubious practice"? That's a strange thing to say... (Or
did you mean you agree that it's a dubious practice? If so, why?)

I agree that replacing protected data with get/set methods is a dubious
practice.
In any case, you either have to have get/set methods, or you have to expose
the data itself, right? I'm confused which it is that you prefer...?

Certainly not! Whatever gave you that idea? If you are programming in the
problem domain instead of just making what BS calls a "bucket of bits" you
would rarely use get/set methods. I often use inspector functions which
*may* correspond to private data items (or I may Google for the return
value -- none of your business!), but I almost always find some other way to
manipulate the object's abstract state than to use a "set" function. In many
simple cases the constructor is all that is needed. In more complex
situations I find the classic idea of thinking of methods as messages quite
helpful.

The problem with excessive use of get/set is that it makes the interface a
thinly disguised C struct.
For me, I tend to use public data for POD structs (e.g., something simple
like a three-d vector with .x, .y and .z members), but I prefer private data
for my more complex classes. However, I do use protected data in some
instances, because I'm generally writing all the classes involved, base and
derived, and it's simply quicker to leave the data as protected and directly
access the members instead of writing a bunch of getters/setters. (There
are also performance issues involved in a few cases, but most of those
involve me deriving from a third-party class that's already made the design
decisions for me.)

As for the visibility of the get/set methods, whether they're protected or
public really depends upon whether I want external code to read or write to
those (perhaps with some kind of checks/asserts/side-effects, etc.), or if
only the derived classes need to read and/or modify those values. If only
derived classes need to know about these "details", the protected
gettters/setters make sense, right? But if they're required information for
the world in general (like the Name of a Person), then surely public
getters/setters are *required*! I mean, if the data itself isn't public,
then what other method of access is there?

Again, I'm kind of amazed. All I can say is that I write a lot of classes
and almost never use the get/set paradigm. The whole point of object
oriented programming is to isolate the interface from the implementation,
but if every data item is required to have a get/set pair, who are you
kidding? I mean, why is that a lot better than public data?
In summary, my take on this is that, well, it all depends! No hard-and-fast
rule is likely to apply to all the needs of all the programmers all the
time. We're paid (well, in general), to make intelligent decisions, and we
ought to be able to justify a given decision by thinking it through in the
first place. So if your boss asks "why is this data private instead of
protected", you shouldn't be answering "because protected data is bad", but
rather you should explain why you made the decision in that particular
case.

I agree that it pays to be flexible but I also think it is a good idea to
adhere to good design practices unless there is some pressing reason not to.
So if my boss asked why this data is private instead of protected, I would
ask her what there is about this situation which might motivate me to adopt
a non-standard design practice.
 

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,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top