Public read-only member

J

Jonathan Lee

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.
 
V

Victor Bazarov

Jonathan said:
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.

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
 
N

Noah Roberts

Jonathan said:
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.

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.
 
A

Andrey Tarasevich

Jonathan said:
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'.
 
J

Juha Nieminen

Jonathan said:
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.
 
J

Jonathan Lee

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
 

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,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top