473,394 Members | 1,887 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

The use of const reference instear of getter

Dear all;

As far as I understand the idea behind getter methods, it is used to
make sure that private memers of a class is returned appropriately to
the calling object.

However, if all I am interested in when making a member private is to
disallow the modification of the value of that member (read-only
member), then how about doing the following:

class A {
public :
const int& ref_to_priv_member;
A() : ref_to_priv_member(priv_member) {
/* Blah */
}

private :
int private_member;
};

I would like to know the opinion of C++ experts on this and if there
are any side-effects of this.
Also from the perferformance point of view, isn't using this mor
effecient than using a getter?

Looking forwards to hearing your opinions.
Aug 4 '08 #1
26 4364
Turin <om*********@gmail.comwrites:
Dear all;

As far as I understand the idea behind getter methods, it is used to
make sure that private memers of a class is returned appropriately to
the calling object.

However, if all I am interested in when making a member private is to
disallow the modification of the value of that member (read-only
member), then how about doing the following:
[...]
I would like to know the opinion of C++ experts on this and if there
are any side-effects of this.
Also from the perferformance point of view, isn't using this mor
effecient than using a getter?

Looking forwards to hearing your opinions.
class A {
public :
const int& ref_to_priv_member;
Instead, do this:

inline int ref_to_priv_member(void) const { return private_member; }

this way you have only a right-value, and if the implementation should
change, you won't have to change the client code (only recompile). On
the other hand, inline member functions will be optimized out and
you'll get the same code as with a data member.

--
__Pascal Bourguignon__
Aug 4 '08 #2
On 2008-08-04 13:31, Turin wrote:
Dear all;

As far as I understand the idea behind getter methods, it is used to
make sure that private memers of a class is returned appropriately to
the calling object.

However, if all I am interested in when making a member private is to
disallow the modification of the value of that member (read-only
member), then how about doing the following:

class A {
public :
const int& ref_to_priv_member;
A() : ref_to_priv_member(priv_member) {
/* Blah */
}

private :
int private_member;
};

I would like to know the opinion of C++ experts on this and if there
are any side-effects of this.
Also from the perferformance point of view, isn't using this mor
effecient than using a getter?
Any good compiler will probably reduce a getter function to the same
thing, with the exception that you can, if you want, easily make changes
to the getter function (such as changing the returned value is certain
cases).

--
Erik Wikström
Aug 4 '08 #3
On 2008-08-04 13:42, Pascal J. Bourguignon wrote:
Turin <om*********@gmail.comwrites:
>Dear all;

As far as I understand the idea behind getter methods, it is used to
make sure that private memers of a class is returned appropriately to
the calling object.

However, if all I am interested in when making a member private is to
disallow the modification of the value of that member (read-only
member), then how about doing the following:
[...]
I would like to know the opinion of C++ experts on this and if there
are any side-effects of this.
Also from the perferformance point of view, isn't using this mor
effecient than using a getter?

Looking forwards to hearing your opinions.
>class A {
public :
const int& ref_to_priv_member;

Instead, do this:

inline int ref_to_priv_member(void) const { return private_member; }
Nitpick:
inline is superfluous since the function is defined in the class
definition, and in C++ we usually write foo() and not foo(void), the
latter is considered bad style.

--
Erik Wikström
Aug 4 '08 #4
On Aug 4, 7:31*am, Turin <omar.ham...@gmail.comwrote:
Dear all;

As far as I understand the idea behind getter methods, it is used to
make sure that private memers of a class is returned appropriately to
the calling object.

However, if all I am interested in when making a member private is to
disallow the modification of the value of that member (read-only
member), then how about doing the following:

class A {
* public :
* * const int& ref_to_priv_member;
* * A() : ref_to_priv_member(priv_member) {
* * * /* Blah */
* * }

* private :
* * int private_member;

};

I would like to know the opinion of C++ experts on this and if there
are any side-effects of this.
Also from the perferformance point of view, isn't using this mor
effecient than using a getter?

Looking forwards to hearing your opinions.
I use the same rule of thumb in this case as I do to determine whether
I should pass an object by const reference to a function - built in
types get passed by value, all others get passed by const reference.

And, BTW, std::string is not a built in type ;).

HTH
Aug 4 '08 #5
In article <7210b453-7a0e-4af3-a159-98f7848d28dd@
34g2000hsh.googlegroups.com>, om*********@gmail.com says...

[ ... ]
However, if all I am interested in when making a member private is to
disallow the modification of the value of that member (read-only
member), then how about doing the following:

class A {
public :
const int& ref_to_priv_member;
A() : ref_to_priv_member(priv_member) {
/* Blah */
}

private :
int private_member;
};

I would like to know the opinion of C++ experts on this and if there
are any side-effects of this.
Also from the perferformance point of view, isn't using this mor
effecient than using a getter?

Looking forwards to hearing your opinions.

This works perfectly well, and doesn't really have any side-effects.

Contrary to the claims elsethread, there's also no real problem in the
(IME unlikely) event that you need to change what's returned -- instead
of using an (explicit) member function, you can create a small proxy
class something like this:

class A {

struct ref_to_priv_member {
friend class A;
operator const int &() { return private_member; }
private:
int private_member;

};
};

Now, if you need to modify what ref_to_priv_member returns, you can do
it in your operator, without any effect on external code.

This does have a couple of _minor_ side effects. First of all, since
only one user-defined operator will be considered in an implicit
conversion sequence, if you were depending on (for example) returning a
reference to constant int, and having that used to construct some other
object (implicitly) this would break the code. IMO, this is a positive
far more often than a negative -- on the rare occasion that such a
conversion is needed, you're probably better off making it explicit,
such as adding a conversion to the inner class that directly creates the
type you want (or adding a ctor to that type that constructs it directly
from this inner class). At the same time, this prevents such implicit
conversions from happening by accident, making the code substantially
safer.

Second, (and usually more importantly) this keeps you from having ugly
code everywhere on the off chance that some day it'll become useful to
have a member function to produce the desired value instead of allowing
"reading a value" to look like reading a value.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 4 '08 #6
Erik Wikström <Er***********@telia.comwrites:
On 2008-08-04 13:42, Pascal J. Bourguignon wrote:
>Turin <om*********@gmail.comwrites:
>>Dear all;

As far as I understand the idea behind getter methods, it is used to
make sure that private memers of a class is returned appropriately to
the calling object.

However, if all I am interested in when making a member private is to
disallow the modification of the value of that member (read-only
member), then how about doing the following:
[...]
I would like to know the opinion of C++ experts on this and if there
are any side-effects of this.
Also from the perferformance point of view, isn't using this mor
effecient than using a getter?

Looking forwards to hearing your opinions.
>>class A {
public :
const int& ref_to_priv_member;

Instead, do this:

inline int ref_to_priv_member(void) const { return private_member; }

Nitpick:
inline is superfluous since the function is defined in the class
definition, and in C++ we usually write foo() and not foo(void), the
latter is considered bad style.
Why?

Is it because it reminds of the C ancestry?

Since I learned C first, I'm always afraid that with foo() it would
accept any number of arguments...

--
__Pascal Bourguignon__
Aug 4 '08 #7
On 2008-08-04 15:54, Pascal J. Bourguignon wrote:
Erik Wikström <Er***********@telia.comwrites:
>On 2008-08-04 13:42, Pascal J. Bourguignon wrote:
>>Turin <om*********@gmail.comwrites:

Dear all;

As far as I understand the idea behind getter methods, it is used to
make sure that private memers of a class is returned appropriately to
the calling object.

However, if all I am interested in when making a member private is to
disallow the modification of the value of that member (read-only
member), then how about doing the following:
[...]
I would like to know the opinion of C++ experts on this and if there
are any side-effects of this.
Also from the perferformance point of view, isn't using this mor
effecient than using a getter?

Looking forwards to hearing your opinions.

class A {
public :
const int& ref_to_priv_member;

Instead, do this:

inline int ref_to_priv_member(void) const { return private_member; }

Nitpick:
inline is superfluous since the function is defined in the class
definition, and in C++ we usually write foo() and not foo(void), the
latter is considered bad style.

Why?

Is it because it reminds of the C ancestry?

Since I learned C first, I'm always afraid that with foo() it would
accept any number of arguments...
Well, for one it is inconsistent. If I write foo(bar) it means that foo
takes one argument of type bar, regardless if bar = void or not (in
other words foo(void) means foo takes one argument of type void). So for
me that means that the only way to call foo would be to somehow supply
an argument of type void.

--
Erik Wikström
Aug 4 '08 #8
On Aug 4, 3:52 pm, Jerry Coffin <jcof...@taeus.comwrote:
In article <7210b453-7a0e-4af3-a159-98f7848d28dd@
34g2000hsh.googlegroups.com>, omar.ham...@gmail.com says...
[ ... ]
However, if all I am interested in when making a member
private is to disallow the modification of the value of that
member (read-only member), then how about doing the
following:
class A {
public :
const int& ref_to_priv_member;
A() : ref_to_priv_member(priv_member) {
/* Blah */
}
private :
int private_member;
};
I would like to know the opinion of C++ experts on this and
if there are any side-effects of this. Also from the
perferformance point of view, isn't using this more effecient
than using a getter?
Looking forwards to hearing your opinions.
This works perfectly well, and doesn't really have any
side-effects.
With most compilers, it will increase the size of the object.
(And since the original poster mentionned performance, I expect
that with most compilers, compared to a getter, it will generate
slower code. Internally, the reference will be implemented as a
pointer, and that ain't good for optimization.)

The other problem is consistency. When you need to return
something that isn't really a member variable, you use a
function call; for the member variable, you use a reference.
Isn't that exposing internal details which the client code
should not be concerned with?

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Aug 4 '08 #9
Turin wrote:
I would like to know the opinion of C++ experts on this and if there
are any side-effects of this.
Also from the perferformance point of view, isn't using this mor
effecient than using a getter?
You have got it completely backwards: Using such a member reference is
going to increase the size of the objects instantiated from the class
(which a member function won't do), it will make instantiating your
class slower (because the reference needs to be initialized) and
accessing the element will be slower (because the compiler will most
probably be unable to optimize the indirection away, as it has no way of
knowing at compile time where the reference is pointing to).

An inline member function will not increment the size of the class,
will have zero overhead at instantiation (and basically anything else),
and will have zero overhead to access the member variable (at least if
the compiler is optimizing).

If what you fear is that a member function will cause slow code,
inlining such a simple member function is one of the easiest
optimizations for any C++ compiler to do. (The only situation where it
will not inline it is when you have all optimizations turned off, eg.
for debugging purposes.)

From an object-oriented point of view your reference is also exposing
the internal implementation details of your class, which the getter
function isn't. (In other words, you could later change the
implementation of your getter function to something completely different
without breaking anything, but you won't be able to do that with your
reference solution.)
Aug 4 '08 #10
pj*@informatimago.com (Pascal J. Bourguignon) wrote:
I'm always afraid that with foo() it would
accept any number of arguments...
The compiler is not broken (at least not in this way,) your fear is
misplaced.
Aug 4 '08 #11
inline int ref_to_priv_member(void) const { return private_member; }
>
this way you have only a right-value, and if the implementation should
change, you won't have to change the client code (only recompile). On
the other hand, inline member functions will be optimized out and
you'll get the same code as with a data member.
So this is nothing more than a standard getter function... ???

The problem with using a const reference is not a problem with the technique
itself, it's a problem with the syntactic limitations of C++ when it comes
to future code maintainability, if your simple getter changes to something
computation (ie. demanding a function) - if that's an issue for you.

class MyClass
{
// constructor omitted for brevity
const int& Age;
}

int main( )
{
MyClass x;
cout << "Age is " << x.Age << endl;
}

So, down the track when "Age" is no longer a simple variable, but a
computation, you will have to change all of your callers because you will
now have to call something like "GetAge( )".

Contrast this to a language like C# which supports the notion of properties,
which lets you do this:

class MyClass
{
public readonly int Age;
}

and then later change it to:

class MyClass
{
public int Age
{
get
{
// get today's date and subtract the date-of-birth to determine "Age
right now"...
return computedAge;
}
}
}

So until such time as C++ has a property system equivalent to above, my
advice is to stick with a function in case it needs to morph into a
computation later, rather than a simple accessor. As the previous poster
noted, the function can still be declared inline and a good compiler will
optimise the overheads away.
Aug 6 '08 #12
class A {
>
struct ref_to_priv_member {
friend class A;
operator const int &() { return private_member; }
private:
int private_member;

};
Second, (and usually more importantly) this keeps you from having ugly
code everywhere on the off chance that some day it'll become useful to
have a member function to produce the desired value instead of allowing
"reading a value" to look like reading a value.
Wow. You seem to have set a really low bar for the definition of "ugly
code", and yet in my opinion are also hypocritical with the suggested
solution (as far as "ugly code" goes).

I don't consider a method declaration/definition like:

int GetAge( ) { return m_Age; }

to really be that much of a journey into "ugly-land". Nor do I consider:

int theirAge = theObj.GetAge( )

to be really stupendously superior to:

int theirAge = theObj.Age;

And yet, to yield a minor gain in readability you suggest the OP does the
following, for each potential member variable which might need to be turned
into a function one day (to avoid *changing* the code-base):
struct ref_to_priv_member {
friend class A;
operator const int &() { return private_member; }
private:
int private_member;

};
And you somehow consider that the above is not in the realm of "ugly code" ?
Is this ugly code more acceptable because there's presumably less of it? How
ugly does this get when there are 20 or 30 members that are "converted" in
this way?

I would rather go back and modify every affected line of my code (ie. to
call a member function rather than access a member variable) rather than
implement *that*.

Unfortunately I think this is an example where "style" is given too much
weight over substance, and the substance (the complexity, maintainability,
and performance of the code) suffers as a result.
Aug 6 '08 #13
In article <u6******************************@posted.internode >,
ke**********@hotmail.com says...

[ ... ]
I don't consider a method declaration/definition like:

int GetAge( ) { return m_Age; }

to really be that much of a journey into "ugly-land". Nor do I consider:
If you never actually used it, this wouldn't be particularly ugly -- but
when you actually use it, ugliness sets in very quickly.
int theirAge = theObj.GetAge( )

to be really stupendously superior to:

int theirAge = theObj.Age;
I don't either -- I consider it substantially _inferior_. As long as the
only use was as you've shown above, it wouldn't be particularly awful,
but that's rarely the case. What gets truly ugly is things like:

a.setSomething(b.getSomething()+b.getSomethingElse ()*c.GetSomething());

which strikes me (at least) as a whole lot less readable than:

a.something = b.something+b.somethingElse*c.something;
And yet, to yield a minor gain in readability you suggest the OP does the
following, for each potential member variable which might need to be turned
into a function one day (to avoid *changing* the code-base):
struct ref_to_priv_member {
friend class A;
operator const int &() { return private_member; }
private:
int private_member;

};

And you somehow consider that the above is not in the realm of "ugly code" ?
Is this ugly code more acceptable because there's presumably less of it? How
ugly does this get when there are 20 or 30 members that are "converted" in
this way?
First of all, if you honestly have 20 or 30 members, chances are pretty
good that what you have is already ugly and poorly designed -- I can
count on my fingers the number of times I've written a class with that
many member variables.

Second, if you're doing this very much, you (of course) gather the
majority of the code into a template, so most of it ends up something
like:

read_only<inta;
read_only<floatb;

That doesn't take care of the "friend" declarations but they're pretty
easy to handle in similar fashion (e.g. it's pretty trivial to create a
macro that defines the proper instantiation of read_only and a friend
declaration for it).

That, of course, is assuming that you really need a friend declaration
at all -- my experience is that it's really fairly rare. When you make
data private, it's normally to enforce some set of constraints on that
data. IME, it's _usually_ better to enforce those constraints directly.
In fact, about 90% of the time, what's really wanted is simply to ensure
that that data is always within a defined range. For that, you can use a
template like this:

#include <exception>
#include <iostream>
#include <functional>

template <class T, class less=std::less<T
class bounded {
const T lower_, upper_;
T val_;

bool check(T const &value) {
return less()(value, lower_) || less()(upper_, value);
}

void assign(T const &value) {
if (check(value))
throw std::domain_error("Out of Range");
val_ = value;
}

public:
bounded(T const &lower, T const &upper)
: lower_(lower), upper_(upper) {}

bounded(bounded const &init)
: lower_(init.lower), upper_(init.upper)
{
assign(init);
}

bounded &operator=(T const &v) { assign(v); return *this; }

operator T() const { return val_; }

friend std::istream &operator>>(std::istream &is, bounded &b) {
T temp;
is >temp;

if (b.check(temp))
is.setstate(std::ios::failbit);
else
b.val_ = temp;
return is;
}
};

This lets you express your constraint directly, something like:

bounded<intx(1,1024);

to say that x should be an int in the range [1..1024). While there
certainly _are_ situations in which that's not what's desired (and it's
not what the OP asked about) I find it fits the bill a whole lot of the
time, and does so much more cleanly than anything with explicit get/set
member functions.

I've also done a version where the range is given as template parameters
instead of ctor parameters. With a few restrictions (e.g. no floating
point ranges) this can cure most performance when/if they arise (though
IME, it's pretty rare). Specifically, this eliminates bounds checking in
the (typical) case of assigning one such bounded object to another of
the same type.
I would rather go back and modify every affected line of my code (ie. to
call a member function rather than access a member variable) rather than
implement *that*.

Unfortunately I think this is an example where "style" is given too much
weight over substance, and the substance (the complexity, maintainability,
and performance of the code) suffers as a result.
Having actual facts based upon years of working with and profiling such
code handicaps me in my desire to agree with you.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 6 '08 #14
In article <bf365953-9c04-4c7d-96eb-ba39699472f4
@z66g2000hsc.googlegroups.com>, ja*********@gmail.com says...

[ ... ]
With most compilers, it will increase the size of the object.
(And since the original poster mentionned performance, I expect
that with most compilers, compared to a getter, it will generate
slower code. Internally, the reference will be implemented as a
pointer, and that ain't good for optimization.)
There _may_ be compilers for which this is true (I certainly can't test
with every one) but a quick test shows that it's not necessarily the
case. I put together a quick bit of test code that created a const
reference to a public variable, and compared the code generated for
accessing the variable directly and via the const reference. Unless I
misread the code, there was on difference between the two.
The other problem is consistency. When you need to return
something that isn't really a member variable, you use a
function call; for the member variable, you use a reference.
Isn't that exposing internal details which the client code
should not be concerned with?
IMO, you've got things exactly backwards: the user is accessing
something that _is_ a member variable, and forcing them to access it via
a function is exposing an internal detail with which they should not be
concerned.

In fact, the representation as a member variable is itself an internal
detail. If what the client is doing (at least conceptually) is just
accessing some data, then the code to do so should _look_ like it's just
accessing data. The previous existence of that data vs. generating it on
the fly is an implementation detail that should be hidden.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 6 '08 #15
On Aug 6, 6:48 am, Jerry Coffin <jcof...@taeus.comwrote:
In article <bf365953-9c04-4c7d-96eb-ba39699472f4
@z66g2000hsc.googlegroups.com>, james.ka...@gmail.com says...
[ ... ]
With most compilers, it will increase the size of the object.
(And since the original poster mentionned performance, I expect
that with most compilers, compared to a getter, it will generate
slower code. Internally, the reference will be implemented as a
pointer, and that ain't good for optimization.)
There _may_ be compilers for which this is true (I certainly can't test
with every one) but a quick test shows that it's not necessarily the
case. I put together a quick bit of test code that created a const
reference to a public variable, and compared the code generated for
accessing the variable directly and via the const reference. Unless I
misread the code, there was on difference between the two.
I'm curious which compiler you tested. A very quick test showed
that the extra reference increased the size of the object with
Sun CC, g++ and VC++.
The other problem is consistency. When you need to return
something that isn't really a member variable, you use a
function call; for the member variable, you use a reference.
Isn't that exposing internal details which the client code
should not be concerned with?
IMO, you've got things exactly backwards: the user is
accessing something that _is_ a member variable, and forcing
them to access it via a function is exposing an internal
detail with which they should not be concerned.
In fact, the representation as a member variable is itself an
internal detail. If what the client is doing (at least
conceptually) is just accessing some data, then the code to do
so should _look_ like it's just accessing data. The previous
existence of that data vs. generating it on the fly is an
implementation detail that should be hidden.
Well, that is really the question. When I mentionned
consistency, the idea I had in mind is that in many cases, you
will be required to use the functional notation, even if the
thing in question is conceptually an "attribute". Since some
attributes require functional access, consistency says that all
should.

It's true that there are ways around this, as you pointed out.
In practice, I've not seen them used much. The idea is
interesting, however: attribute access should always use
variable access syntax, even if it means introducing some sort
of proxy.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Aug 6 '08 #16
Jerry Coffin <jc*****@taeus.comwrote:
ja*********@gmail.com says...
The other problem is consistency. When you need to return
something that isn't really a member variable, you use a
function call; for the member variable, you use a reference.
Isn't that exposing internal details which the client code
should not be concerned with?

IMO, you've got things exactly backwards: the user is accessing
something that _is_ a member variable, and forcing them to access it via
a function is exposing an internal detail with which they should not be
concerned.
Why is the *user* insisting that it has to be a member-variable? What
business is it of the user to decide what bits of the object are stored
and what bits are calculated?
Aug 6 '08 #17
In article <da****************************@earthlink.vsrv-
sjc.supernews.net>, da******@earthlink.net says...

[ ... ]
Why is the *user* insisting that it has to be a member-variable? What
business is it of the user to decide what bits of the object are stored
and what bits are calculated?
As I said in the part of the post that you snipped, the fact that it's a
member variable is, itself, an implementation detail the user/client
should be able to ignore.

The real question is whether (at least at a conceptual level) the user
is asking for some data, or asking for an action to be carried out. IMO,
when the user is simply asking for some data, the code they write should
look like it's just accessing data, even if (as an implementation
detail) that data happens to be generated on the fly instead of just
returned from storage.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 6 '08 #18
In article <a04e37a8-a709-40f6-ba20-7a783640d3bf@
79g2000hsk.googlegroups.com>, ja*********@gmail.com says...

[ ... ]
There _may_ be compilers for which this is true (I certainly can't test
with every one) but a quick test shows that it's not necessarily the
case. I put together a quick bit of test code that created a const
reference to a public variable, and compared the code generated for
accessing the variable directly and via the const reference. Unless I
misread the code, there was on difference between the two.

I'm curious which compiler you tested. A very quick test showed
that the extra reference increased the size of the object with
Sun CC, g++ and VC++.
I tested with g++ and VC++. I didn't look at the size of the object
file, but at the generated code -- the size of the object file can be
affected by all sorts of things unrelated to the actual code.

[ ... ]
The idea is
interesting, however: attribute access should always use
variable access syntax, even if it means introducing some sort
of proxy.
I'll admit that sometimes it may be more work than it's worth -- but I
think the use of an accessor function should be recognized for what it
really is. Accessor functions represent a compromise in which you make a
class easier to implement at the expense of being more difficult (and
ugly) to use. That's directly contrary to (what I'd see as) the basic
point of using objects to start with though -- that it's worthwhile to
do extra work in implementing a class to make it easier to use.

Of course, there are limits to this: making an class 100 times more
difficult to implement in the interest of making it .01 percent easier
to use is only justified if you use that class a LOT. Again, however,
this should be seen for what it is: a decision that at least in this
case, the ideal just isn't worth the effort. I, however, think most code
can quite economically approach the ideal much more closely than is
routinely seen today -- but most people have gotten so accustomed to
such compromises that they've lost sight of the ideal (or, often, never
really even considered what the ideal should be).

There's also the simple fact that most languages lack the features
necessary to do the job correctly. In a mixed-language environment, it
may be reasonable to pick a greatest common denominator feature set
that's consistent across the languages. This may dictate accessor
functions throughout. Again, this should be seen for what it is: it's
not really the "right" way to use C++, but simply a compromise in which
you sacrifice readability of the C++ portion of the job for consistency
with the part implemented in the other language.

IMO, this is _usually_ a poor compromise though -- if consistency
matters that much for you, chances are pretty good that you'd be better
off just using one language throughout. Again, real-world compromises
often render that impractical though...

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 6 '08 #19
On Aug 6, 5:09 pm, Jerry Coffin <jcof...@taeus.comwrote:
In article <a04e37a8-a709-40f6-ba20-7a783640d3bf@
79g2000hsk.googlegroups.com>, james.ka...@gmail.com says...
[ ... ]
There _may_ be compilers for which this is true (I
certainly can't test with every one) but a quick test
shows that it's not necessarily the case. I put together a
quick bit of test code that created a const reference to a
public variable, and compared the code generated for
accessing the variable directly and via the const
reference. Unless I misread the code, there was on
difference between the two.
I'm curious which compiler you tested. A very quick test
showed that the extra reference increased the size of the
object with Sun CC, g++ and VC++.
I tested with g++ and VC++. I didn't look at the size of the
object file, but at the generated code -- the size of the
object file can be affected by all sorts of things unrelated
to the actual code.
I didn't look at the size of the object file. I looked at the
size of the object. In an array. Basically:

class A1
{
public:
int const& r ;
A1( int i ) : r( myI ), myI( i ) {}

private:
int myI ;
} ;

class A2
{
public:
A2( int i ) : myI( i ) {}
int r() const { return myI ; }

private:
int myI ;
} ;

On all of my machines, sizeof( A2 ) is 4. Depending on the
machine, sizeof( A1 ) is either 8 or 16.

For occasional use, it doesn't matter, but if you've got a large
array of the things, it could make a significant difference.

Most of the time, too, I don't have intermodule optimization
turned on, so if the constructor isn't inline, and the compiler
can't see what the reference was initialized with, it will have
to generate an additional level of indirection for each access.
(If the constructor is inline, of course, it shouldn't be too
difficult for the compiler to opimize, but it wouldn't surprise
me either if some didn't.)
[ ... ]
The idea is
interesting, however: attribute access should always use
variable access syntax, even if it means introducing some sort
of proxy.
I'll admit that sometimes it may be more work than it's worth -- but I
think the use of an accessor function should be recognized for what it
really is. Accessor functions represent a compromise in which you make a
class easier to implement at the expense of being more difficult (and
ugly) to use. That's directly contrary to (what I'd see as) the basic
point of using objects to start with though -- that it's worthwhile to
do extra work in implementing a class to make it easier to use.
Yes. In many ways, and accessor function can be considered a
hack around language constraints. If the element is logically
considered to be an attribute; of course.

[A number of interesting considerations deleted...]

In the end, I guess, it's a question of making the rules simple
(either none or all of the data is public), and following
general practice (which isn't that bad), even though there are
better (cleaner, more elegant) solutions.

(In our case, we use functions for access even in our pure data
classes. Justified in this particular case by the fact that the
actual data class itself is automatically generated, with code
to support marshalling and data base accesses, but without any
code to support constraints, etc. The access functions are
virtual, and the actual code derives from the generated class to
implement the additional constraints. I'm not sure how to make
that work with your idea using proxies.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Aug 6 '08 #20
On Aug 6, 1:37 pm, "Daniel T." <danie...@earthlink.netwrote:
Jerry Coffin <jcof...@taeus.comwrote:
james.ka...@gmail.com says...
The other problem is consistency. When you need to return
something that isn't really a member variable, you use a
function call; for the member variable, you use a reference.
Isn't that exposing internal details which the client code
should not be concerned with?
IMO, you've got things exactly backwards: the user is
accessing something that _is_ a member variable, and forcing
them to access it via a function is exposing an internal
detail with which they should not be concerned.
Why is the *user* insisting that it has to be a
member-variable? What business is it of the user to decide
what bits of the object are stored and what bits are
calculated?
The user isn't. The design says that this type has such and
such attributes. The design of std::list<>, for example, says
that a list has an attribute size. It's logically (read-only)
data, not a function.

In my own code, I use functions, rather than public access, for
a variety of technical reasons (and for consistency, in the
cases where the technical reasons don't actually apply). But
the naming conventions still hold: a function has a verb or verb
phrase as a name, data (such as an attribute) a noun. If the
function returns something that isn't logically an attribute of
the object, it will have a verb phrase as a name, something like
get...(), or calculate...(), or create...(). For attributes,
however, I use the convention:

Type dataName() const ;
Type /* or void */ dataName( Type const& newValue ) ;

(If it's not too expensive, and might make sense in some cases,
I'll have the setter return the old value, so that the client
code can save and restore it.)

There are reasons why you might prefer the function---I gave an
example in my latest response to Jerry, where the access had to
be virtual. But the fact remains that it is compromise, based
on technical reasons; from the design point of view, I'm dealing
with attributes, not behavior.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Aug 6 '08 #21
James Kanze <ja*********@gmail.comwrote:
"Daniel T." <danie...@earthlink.netwrote:
Jerry Coffin <jcof...@taeus.comwrote:
james.ka...@gmail.com says...
The other problem is consistency. When you need to return
something that isn't really a member variable, you use a
function call; for the member variable, you use a reference.
Isn't that exposing internal details which the client code
should not be concerned with?
IMO, you've got things exactly backwards: the user is
accessing something that _is_ a member variable, and forcing
them to access it via a function is exposing an internal
detail with which they should not be concerned.
Why is the *user* insisting that it has to be a
member-variable? What business is it of the user to decide
what bits of the object are stored and what bits are
calculated?

The user isn't. The design says that this type has such and
such attributes. The design of std::list<>, for example, says
that a list has an attribute size. It's logically (read-only)
data, not a function.

In my own code, I use functions, rather than public access, for
a variety of technical reasons (and for consistency, in the
cases where the technical reasons don't actually apply). But
the naming conventions still hold: a function has a verb or verb
phrase as a name, data (such as an attribute) a noun. If the
function returns something that isn't logically an attribute of
the object, it will have a verb phrase as a name, something like
get...(), or calculate...(), or create...(). For attributes,
however, I use the convention:

Type dataName() const ;
Type /* or void */ dataName( Type const& newValue ) ;

(If it's not too expensive, and might make sense in some cases,
I'll have the setter return the old value, so that the client
code can save and restore it.)

There are reasons why you might prefer the function---I gave an
example in my latest response to Jerry, where the access had to
be virtual. But the fact remains that it is compromise, based
on technical reasons; from the design point of view, I'm dealing
with attributes, not behavior.
I agree with you. The two primary points of agreement are (1)
consistency, and (2) compromise.

The getter should not betray wither the value is stored or calculated.
The simplest way to do that in C++ is to make all member-variables
private and use member-functions that simply return the
member-variable's value (as a copy usually, but a const reference can be
used as an optimization IMHO.) Other languages have other ways. Ways
that allow the writer to distinguish data retrieval from requests.

If we were in comp.object or some other general programming group, you
would have a case, however this is comp.lang.c++ and in this language,
the solution is private data and public getters.
Aug 6 '08 #22
In article <ba52a49b-37ee-478d-8a50-1fa82aa11a74
@w7g2000hsa.googlegroups.com>, ja*********@gmail.com says...

[ ... ]
There are reasons why you might prefer the function---I gave an
example in my latest response to Jerry, where the access had to
be virtual. But the fact remains that it is compromise, based
on technical reasons; from the design point of view, I'm dealing
with attributes, not behavior.
Perhaps you could go into more detail about exactly what you're doing --
I haven't quite gotten straight why you can't use a proxy for your
situation. I'm sure you're well aware that a conversion operator can be
virtual, so there's clearly more to it than that...

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 7 '08 #23
In article <9b54a587-9429-4bb3-a2de-3a0db88c74bb@
2g2000hsn.googlegroups.com>, ja*********@gmail.com says...

[ ... ]
If I understand you correctly, fundamentally, you disagree with
the convention. I can understand that; it's not perfect. On
the other hand, it's very well established, and it doesn't cause
any real problems, either. So IMHO, there's no point in
fighting to change it; the eventual advantages simply aren't
worth the effort. And changing your code, without changing the
established convention, is counter-productive; because you don't
follow the established convention, people have more trouble
reading and understanding the code.
I feel guilty if I don't at least make a token attempt -- nothing is
likely to get better if the (apparently few) people who recognize a
problem don't make any attempt at improving the situation.

Yes, I suppose it's a waste of time to try to fight something most
people consider settled. People respond to hype, not reality. The fact
that this addresses one of the most serious problems in programming
means it gets ignored. If you're going to take over the world, you have
to start by addressing problems nobody's ever really had...

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 8 '08 #24
On Aug 8, 6:04 am, Jerry Coffin <jcof...@taeus.comwrote:
In article <9b54a587-9429-4bb3-a2de-3a0db88c74bb@
2g2000hsn.googlegroups.com>, james.ka...@gmail.com says...
[ ... ]
If I understand you correctly, fundamentally, you disagree
with the convention. I can understand that; it's not
perfect. On the other hand, it's very well established, and
it doesn't cause any real problems, either. So IMHO,
there's no point in fighting to change it; the eventual
advantages simply aren't worth the effort. And changing
your code, without changing the established convention, is
counter-productive; because you don't follow the established
convention, people have more trouble reading and
understanding the code.
I feel guilty if I don't at least make a token attempt --
nothing is likely to get better if the (apparently few) people
who recognize a problem don't make any attempt at improving
the situation.
Yes, I suppose it's a waste of time to try to fight something
most people consider settled. People respond to hype, not
reality. The fact that this addresses one of the most serious
problems in programming means it gets ignored. If you're going
to take over the world, you have to start by addressing
problems nobody's ever really had...
:-)

Still, I think that there are enough real problems that we have
to choose; we can't solve them all. And (maybe just because of
habit) this one doesn't seem that serious---I may need an extra
(), but I still do make the distinction you're concerned about
in my naming conventions. (Actually, while it hadn't occurred
to me that the () were wrong, until your posting, I often had
the impression that I was the only person who felt that there
was a distinction here---that a "getter" wasn't conceptually a
function, and shouldn't have a verb, like "get", in its name.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Aug 8 '08 #25
James Kanze <ja*********@gmail.comwrote:
Jerry Coffin <jcof...@taeus.comwrote:
james.ka...@gmail.com says...

[ ... ]

Yes, I suppose it's a waste of time to try to fight something
most people consider settled. People respond to hype, not
reality. The fact that this addresses one of the most serious
problems in programming means it gets ignored. If you're going
to take over the world, you have to start by addressing
problems nobody's ever really had...

:-)

Still, I think that there are enough real problems that we have
to choose; we can't solve them all. And (maybe just because of
habit) this one doesn't seem that serious---I may need an extra
(), but I still do make the distinction you're concerned about
in my naming conventions. (Actually, while it hadn't occurred
to me that the () were wrong, until your posting, I often had
the impression that I was the only person who felt that there
was a distinction here---that a "getter" wasn't conceptually a
function, and shouldn't have a verb, like "get", in its name.)
Bertrand Meyer figured it out. :-) I'm still waiting for someone in the
OO community to come up with something he didn't already cover. :-)
Aug 8 '08 #26
In article <da****************************@earthlink.vsrv-
sjc.supernews.net>, da******@earthlink.net says...

[ ... ]
Bertrand Meyer figured it out. :-) I'm still waiting for someone in the
OO community to come up with something he didn't already cover. :-)
Covariant parameter safety.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 8 '08 #27

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: gouki | last post by:
class X { // members public: int foo() const; } int X::foo() const // what is the const for??? {
3
by: Shreyas Ranade | last post by:
I want to pass an Object Reference to a C# function, but also I want to make sure that the calling function should not change it's value. The C++ Code Like MyClass cls; Fun1(cls) void...
7
by: th-ko | last post by:
Hi, I would like to know whether a certain coding pattern exist to handle the following problem. I am using a const methode to get and value a from the class. In case the value was not calculated...
4
by: wenmang | last post by:
Hi, I like to use a const pointer to a shm inside a class, and I don't want to instantiate it through class ctor, is there any other way around? The main purpose for const pointer is to avoid...
4
by: grizggg | last post by:
I have searched and not found an answer to this question. I ran upon the following statement in a *.cpp file in a member function: static const char * const pacz_HTMLContentTypeHeader =...
4
by: Noah Roberts | last post by:
I am trying to keep a vector of tuples sorted based on the first member and so for my insert function I am calling std::lower_bound with a bound comparator like the following: ...
8
by: Ruben | last post by:
error: passing `const Weight' as `this' argument of `float Weight::wgt()' discards qualifiers seems to be some sort of standard error format that I'm not understanding. I have code that...
6
by: .rhavin grobert | last post by:
hello;-) i frequently need the following construction: ReturnParam § Function() § { /...do something.../ someType var § = something; /...do something.../ return something;
1
by: rottmanj | last post by:
I have written a class that manages all the database connection information/methods I need to connect to a database and query off of it. In order to make my application dynamic so that it can read...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.