Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Public read-only member

0 views
Skip to first unread message

Jonathan Lee

unread,
Apr 23, 2009, 11:31:35 AM4/23/09
to
So I've seen on some web sites a solution for the problem of having a
class member that is public and read-only. Probably you've all seen
this, but basically it makes a reference to a private member, and adds
a const:

class SoundEffect {
public:
SoundEffect() : bitrate(_bitrate) { };
long const & bitrate;
private:
long _bitrate; // Info the user might want, but class doesn't
use.
}

Personally, I don't mind this approach over a getBitrate() member
_supposing_ that the value of "_bitrate" is not essential to the
operation of SoundEffect. i.e., if someone worked around the const and
changed "_bitrate", it wouldn't be that important.

I'm wondering if there are other caveats to this method. To me it
seems friendlier for the user of the class, but maybe I'm overlooking
something.

Victor Bazarov

unread,
Apr 23, 2009, 11:40:07 AM4/23/09
to

It's somewhat contrived (my fault, I guess). Caveat is that such a way
of implementing an accessor does not adhere to *value semantics* the
"normal" method would provide. Supposing that the "normal" method
returns a 'long'

long getBitrate() const;

the user would never be able to take the address of it since it's a
temporary. With the const ref approach nothing really prevents me from
doing

long const* pBitrate = &someSoundEffect.bitrate;

and then I'm not going to know when 'pBitrate' is no longer valid. Not
that there is much wrong with that, of course, but still...

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Noah Roberts

unread,
Apr 23, 2009, 12:03:38 PM4/23/09
to

You'll not be able to change your bitrate value to a calculation. Any
time you use variable syntax to get or set a value in a class you are
stuck with variable syntax. This is why any I/O to a class should be
function syntax as it then removes this problem. The clients don't know
if they're reading a variable or asking for a calculation...and they
shouldn't.

This problem goes further. You could realize someday that SoundEffect
should be subclassed. Now you're stuck with a bitrate variable again.
You can't override how it's provided.

If you know that you're never going to change how bitrate is
calculated/provided then you've nothing to worry about. Problem is that
every time you say "never" you should stop what you're doing and ask
yourself if that's really a necessary aspect of the problem or if you're
just thinking wishfully.

Andrey Tarasevich

unread,
Apr 23, 2009, 12:47:51 PM4/23/09
to
Jonathan Lee wrote:
>
> I'm wondering if there are other caveats to this method. To me it
> seems friendlier for the user of the class, but maybe I'm overlooking
> something.

You are indeed exposing the member as read-only (ignoring the
possibility of a malicious 'const_cast' for now), but for some reason
you seem to make an effort to expose it as an _lvalue_. If you really to
expose it in this specific way (as an lvalue), then it might be a fine
approach. But the lvalue-ness is not absolutely required, I don't see
much point in doing it this way.

If you really prefer to access that member through the data-member-style
syntax (as opposed to calling a getter function), a more elegant
solution might be to use on of the various available implementations of
so-called "properties". In short, instead of exposing a naked
const-reference, wrap that reference into a data member of class type
with overloaded 'operator long() const'.

--
Best regards,
Andrey Tarasevich

Juha Nieminen

unread,
Apr 23, 2009, 3:33:57 PM4/23/09
to
Jonathan Lee wrote:
> class SoundEffect {
> public:
> SoundEffect() : bitrate(_bitrate) { };
> long const & bitrate;
> private:
> long _bitrate; // Info the user might want, but class doesn't
> use.
> }

Two practical issues:

1) The reference will increase the size of the class, whereas a getter
function won't. (Whether this is an issue depends on how much the class
will be instantiated.)

2) The compiler will be unable to create a default copy constructor and
copy assignment operator for your class, so if you want it to be
copyable and assignable, you will have to create them manually.

And of course exposing internal details of the class breaks
abstraction, with all of its consequences.

Daniel T.

unread,
Apr 23, 2009, 10:37:52 PM4/23/09
to
Jonathan Lee <cho...@shaw.ca> wrote:

Consistency is important. When clients access calculated traits of your
class, they have to call a function, but stored traits (using the above)
don't need function calls. Why force the client to keep track of which
traits your class happens to store and which it happens to calculate?

The uniform access principle is your friend.

Jonathan Lee

unread,
Apr 24, 2009, 11:06:42 AM4/24/09
to
Hi all,
Those are all very good points. Actually, after some consideration,
it looks like the traditional method has many advantages. Thanks to
all for the advice
--Jonathan

blargg

unread,
Apr 24, 2009, 3:58:03 PM4/24/09
to

That's actually the reason for wanting a such a read-only member. With
such a thing, one can unify abstract values AND data members of a struct
with a uniform access syntax. But C++ lacks the features to support this
in a practical way, so it's not something to try. And based on informal
research into how it might work in C++, I'm not sure support for such a
thing would ever lead to clearer programs, even if it were implemented
very cleanly in the language, since objects should be primarily
abstracting BEHAVIOR, not state (even if merely abstract).

LiShuJun

unread,
Apr 26, 2009, 3:55:09 AM4/26/09
to
_bitrate = ???
"Jonathan Lee" <cho...@shaw.ca>
??????:86052278-4a48-443e...@v15g2000yqn.googlegroups.com...
0 new messages