Question on Myers #30

M

Master of C++

Hi,

In Effective C++, #30, Myers says:

"Avoid member functions that return pointers or references to members
less accessible than themselves"

But, operator[] does exactly the opposite. Is overloading operator[]
considered "evil" in C++ circles ? I write a lot of numerical
programming code, and such operators make life easier for me.

Thanks,
Vijay.
 
A

Alf P. Steinbach

* Master of C++:
In Effective C++, #30, Myers says:

"Avoid member functions that return pointers or references to members
less accessible than themselves"

But, operator[] does exactly the opposite. Is overloading operator[]
considered "evil" in C++ circles ? I write a lot of numerical
programming code, and such operators make life easier for me.

"Effective C++" et.al. is just a compendium of rules-of-thumbs for
newbies. Very good for that, not very good when you understand the
issues and can apply intelligence rather then rote rules. The advice
cited above is, however, good for nothing... ;-)

A member function that returns a pointer or reference to a member
as accessible or more accessible than itself, is usually meaningless.

Perhaps the above is just a typo.
 
I

Ioannis Vranos

Alf said:
A member function that returns a pointer or reference to a member
as accessible or more accessible than itself, is usually meaningless.

Perhaps the above is just a typo.


I am not for the "usually" part. I am using many methods returning const
references, references or pointers to data members.
 
I

Ioannis Vranos

Ioannis said:
I am not
sure

for the "usually" part. I am using many
API

methods returning const
references, references or pointers to data members.
 
A

Alf P. Steinbach

* Ioannis Vranos:
Well, are you for example calling a public member function getHeight()
to obtain a reference to a public member mHeight, height_, myHeight?

Or a protected member function to obtain a reference to a protected
member, or a private one to obtain a reference to a private one?

That's what I think is usually very meaningless; the protection level of the
data member is then IMO not strict enough (which except for the "usually"
excludes private member function returning reference to private member,
but there might be a case for a virtual such).

I may be wrong though.

Perhaps if someone could quote or describe Myers' rationale?
 
I

Ioannis Vranos

Alf said:
Well, are you for example calling a public member function getHeight()
to obtain a reference to a public member mHeight, height_, myHeight?



Actually yes, this one in the form of (system-dependent) properties
implemented as getheight() and setheight() methods, which are implicitly
called.


But let's stick in another portable example:

vector's operator[] doesn't return a reference? Or begin() an iterator?


Isn't the following style common?


class SomeClass
{
string name;

// ...

public:

const string &getname() const { return name; }

void setname(const string &newname) { name= newname; }

// ...
};
 
A

Alf P. Steinbach

* Ioannis Vranos:
Actually yes, this one in the form of (system-dependent) properties
implemented as getheight() and setheight() methods, which are implicitly
called.

Hm, not sure what you mean.

But let's stick in another portable example:

vector's operator[] doesn't return a reference? Or begin() an iterator?

They do, and the members they return references to are less accessible
(contrary to Meyers' advice).

Isn't the following style common?


class SomeClass
{
string name;

// ...

public:

const string &getname() const { return name; }

void setname(const string &newname) { name= newname; }

// ...
};

Yep, and again, contrary to Meyers' advice. Although I'd return that
string by value and let the compiler to the optimization.
 
I

Ioannis Vranos

Alf said:
Yep, and again, contrary to Meyers' advice. Although I'd return that
string by value and let the compiler to the optimization.


If you return the string by value most chances are that you will have a
redundant call to the copy constructor of the string for the temporary,
with a full copy of all its members.


In strings and other containers with large size, this is a major
drawback. That's why we have references and pointers.


I am not sure what Meyers means with that quote, but only he can explain
what he means exactly. The bottom line is, one should use const
references and const pointers instead of redundant temporaries, as much
as he can.


Perhaps Meyers means non-const references and pointers specifically, and
not the const ones. That is, I could agree with this:


"Avoid member functions that return non-const pointers or references to
members less accessible than themselves".
 
M

Master of C++

Of course, I don't follow EC++ as if it were a rule-book. But a lot of
well-respected authors (Herb Sutter, Steve McConnell etc.,) cite Myers
heavily, and I have respect for what he says in his book. Thats what
makes this advice a little confusing.

Its not a typo. I verified it before posting.

-Vijay.
 
T

tair.sabirgaliev

if you are overloading operator[] for example for Array class, it is
not contrary to Myers, because Myers said that for general design, but
I think CONTAINER classes are exception to this rule.
 
P

Phil Staite

Master said:
Hi,

In Effective C++, #30, Myers says:

"Avoid member functions that return pointers or references to members
less accessible than themselves"

Seems straightforward to me. IMHO if you give out a pointer or
reference to any data member you're violating encapsulation. (but yes,
sometimes it has to be done) As Mr. Meyers points out, giving out
pointers or refs to data members with more restricted access (eg. a
public member function returning a pointer to a private member) is even
worse. Heck, you might as well just make the member public and call it
a struct... ;-)

Additionally, just the fact that you're returning pointers/refs to data
members is suspect. Generally that means your data is in one place or
class, and the code that operates on it is in another. Not good for
encapsulation. And yes, I know there are many many exceptions to this
idea and instances where you just "have to" expose data/members in some
ways. I'm just saying if you're doing that, make sure you're doing it
for a good/valid reason.
 
R

Rances

Phil Staite said:
Seems straightforward to me. IMHO if you give out a pointer or reference
to any data member you're violating encapsulation. (but yes, sometimes it
has to be done)

PUblic functions returning const references to large private data members
such as vectors is a pretty good design pattern IMO. You can use the
reference in a const manner very efficiently, or use an inneficient copy in
a non-const manner.
 
I

Ioannis Vranos

Rances said:
PUblic functions returning const references to large private data members
such as vectors is a pretty good design pattern IMO. You can use the
reference in a const manner very efficiently, or use an inneficient copy in
a non-const manner.


Also, a return of a const reference or const pointer to something does
not necessarily expose the internal data of a class, although in most
times it is internal data of the class, however it may be not, and thus
it is not against data hiding.


Bottom line is, returning a redundant string temporary which is a copy
of an internal string member does not provide any more data hiding than
a const reference or pointer to the same string member.
 
W

White Wolf

Master said:
Of course, I don't follow EC++ as if it were a rule-book. But a lot of
well-respected authors (Herb Sutter, Steve McConnell etc.,) cite Myers
heavily, and I have respect for what he says in his book. Thats what
makes this advice a little confusing.

No, they don't.
Its not a typo. I verified it before posting.

It is a typo. The book is written by Scott Meyers.
 
A

Alf P. Steinbach

* Ioannis Vranos:
Also, a return of a const reference or const pointer to something does
not necessarily expose the internal data of a class, although in most
times it is internal data of the class, however it may be not, and thus
it is not against data hiding.
Agreed.


Bottom line is, returning a redundant string temporary which is a copy
of an internal string member does not provide any more data hiding than
a const reference or pointer to the same string member.

Well, the reference actually _is_ an exposure. A common case where this may
bite you (at least it tried to gnaw some meat off my leg, I just
kicked it very hard and never seen it since) is where you want to change the
internal implementation so you no longer have a member. It's probably a
purely philosophical question where the blame really is, then: the reference
result, versioning, ill-behaved client code, what, but in practice problems
can be avoided simply by avoiding the reference result in the first place. As
I see it it's definitely a case of Knuth's evil premature optimization.
Keeping one's set of options open is, after all, the favorite strategy of good
programmers, who thereby are lazy by definition, I find that interesting....
 
I

Ioannis Vranos

Alf said:
Well, the reference actually _is_ an exposure. A common case where this may
bite you (at least it tried to gnaw some meat off my leg, I just
kicked it very hard and never seen it since) is where you want to change the
internal implementation so you no longer have a member. It's probably a
purely philosophical question where the blame really is, then: the reference
result, versioning, ill-behaved client code, what, but in practice problems
can be avoided simply by avoiding the reference result in the first place. As
I see it it's definitely a case of Knuth's evil premature optimization.
Keeping one's set of options open is, after all, the favorite strategy of good
programmers, who thereby are lazy by definition, I find that interesting....


If you want to keep the old programming interface of your class, you can
easily change const string & to const string.


If you were returning a non-const reference(!) to your internal data
member, then you shouldn't do it.


What Meyers is saying is absolutely right for non-const references, and
my guess is that it is what he means.
 
A

Alf P. Steinbach

* Ioannis Vranos:
If you want to keep the old programming interface of your class, you can
easily change const string & to const string.

Not without potentially breaking client code.

If you were returning a non-const reference(!) to your internal data
member, then you shouldn't do it.
Right.


What Meyers is saying is absolutely right for non-const references, and
my guess is that it is what he means.

That doesn't seem to follow.
 
A

Alf P. Steinbach

* Ioannis Vranos:
May you provide an example?


void client( bool thisOrThat )
{
std::string const gwb = "Bah!";
std::string const* ps = thisOrThat? &gwb : &iv.getstring();

std::cout << *ps << std::endl;
}
 

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

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top