Why are Set & Get important?

I

Immortal Nephi

The base class has some data members. Tens of member functions or
hundreds of member functions modify data members. What if programmer
make mistakes? They might assign incorrect value to the data
members. Then, they have to examine all tens of member functions or
hundreds of member functions to try and locate incorrect values. They
waste their time. They have difficulties to find a bug.
Set and Get member functions are the answer. They can guard against
incorrect value in the data members. The programmers do not have to
examine all member functions. They can only locate set or get member
function before they can easily correct incorrect values. It saves
more time.
Can C++ Compiler inline set and get member functions to improve
optimization? Then data members should be set to private. Set and
Get member functions will be inherited into derived class.
Please take a look at my code. It gives you some ideas. Tell me
your opinion. Is it worth best C++ practice?

typedef unsigned char ubyte;
typedef unsigned short int uword;

class A
{
public:
A() : m_data( 0 ), m_flag( 0 ) {}
~A() {}

void set_data_low_byte( ubyte data )
{
m_data &= 0xFF00;
m_data |= data;
}

void set_data_high_byte( ubyte data )
{
m_data &= 0xFF;
m_data |= ( data << 8 );
}

void set_data_word( uword data )
{
m_data = data;
}

ubyte get_data_low_byte() const
{
return m_data;
}

ubyte get_data_high_byte() const
{
return m_data >> 8;
}

uword get_data_word() const
{
return m_data;
}

void set_flag( ubyte flag )
{
m_flag = flag & 1;
}

ubyte get_flag() const
{
return m_flag;
}

private:
uword m_data;
ubyte m_flag;
};


class B : public A
{
public:
B() {}
~B() {}

void F1()
{
uword data = 0xF0;
data += 0X30;

set_data_low_byte( data ); // Assign 0x20 to low byte and ignore
high byte
set_flag( 3 ); // Replace from 3 to 1 by default
}

void F2()
{
uword data = get_data_low_byte();
data += 0X430;

set_data_high_byte( data ); // Assign 0x50 to high byte
if( get_flag() )
set_flag( 0 );
}

void F3()
{
uword data = get_data_word();
data += 0x2C5;
set_data_word( data );
}
};


int main()
{
B b;

b.F1();
b.F2();
b.F3();

return 0;
}
 
J

Jonathan Lee

        Can C++ Compiler inline set and get member functions to improve
optimization?

Yes, and you've actually done it by defining the getters/setters in
the class body. See

http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.8

and also the FAQ just before it.
        Please take a look at my code.  It gives you some ideas..  Tell me
your opinion.  Is it worth best C++ practice?

I prefer not to pollute the class declaration with function bodies. I
think that's the prevailing opinion as well. Getters and setters
aren't usually a drag on performance.

--Jonathan
 
I

Immortal Nephi

Yes, and you've actually done it by defining the getters/setters in
the class body. See

 http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.8

and also the FAQ just before it.


I prefer not to pollute the class declaration with function bodies. I
think that's the prevailing opinion as well. Getters and setters
aren't usually a drag on performance.

Why do you prefer that function body be defined inside header? Why
not use proxy class? Interface and implementation's header and source
codes are hidden from the clients. The client can only examine data
members and function members in proxy class in header, but they are
unable to see the function body.

Proxy class requires first or second indirection. After interface and
implementation's header and source codes are optimized into static
library or DLL library. You can always include proxy class header
into your project. I wonder second indirection may be overhead on CPU.
 
N

Noodge

On Jun 25, 1:16 pm, Immortal Nephi =
[snip]
        Set and Get member functions are the
[snip]

Set and get are a very thin layer of abstraction.
They are probably better than direct access to
public data members. But only just.

What you want to do is design your classes as
exporters of functionality. In most cases, not
all of course but most, the data members should
not be visible, not even through get/set.

Suppose you are a client of a class, call it X.

And suppose
you know that it stores some internal state as,
for example, a long. You are going to have the
temptation to shadow this internal long. For
example, you may be away from the class X for
a long time and don't want to have to go back
to it to get the status. You may be tempted to
calculate it yourself. Or you may be tempted to
do things that depend on the status fitting in
a long. Or you may be tempted to try things like
setting the status (through the set accessor)
to a value that you want to use for *your*
purposes instead of the class X's purposes.

Then the author of class X makes some change.
Maybe adding another value to the possible
set of status values. And boom! The rest of
the code that depended on how it *used to*
arrange the values of that long data member.

Instead, the status should be hidden. If the
class X needs to report on status it should
be all defined in the interface through a
nice contract. Say it's a printer handler.
So you have GetPrinterStatus(), which will
return some contracted set of values. And
the clients don't ever know there's a long
data variable to set the value of. Because
in the other direction you have Shutdown()
or LockPrinter(std::string &PassWord) and
so on and so forth.

See then, from the client view, there's no
temptation of making assumptions based on
the printer having one long data variable
for its status. Indeed, there might even
not *be* a data variable with the status.
The class might check itself and work out
the status when required. Or fetch it from
the hardware it was managing, etc.
Socks
 
J

Jonathan Lee

Why do you prefer that function body be defined inside header?

I think you misunderstood me. I *don't* prefer this. I prefer that the
header not contain anything executable. The function body, in my
opinion, should exist in the classname.cpp source. I don't have any
fundamental reason for this -- just that I know where my executable
code is. I've tried a couple times having inline functions in the
header, but it quickly becomes a nuisance. You start making changes in
the cpp file and then you think "Hey, I got to change MyClass::getData
()." But then it's in a different file... Better just to keep it all
in one place.
Why not use proxy class?

The better question is: why use a proxy class? If you have some need
for it, go ahead. But what are you proposing? That you wrap the setter/
getter in a proxy class? So that there's another setter/getter? That
doesn't make much sense to me.
 You can always include proxy class header into your project.

Are you just concerned about hiding the private details of your class
from a client using your code? You might want to do that in certain
instances, but I wouldn't adopt the practice in general. That'd be a
lot of proxy classes...

--Jonathan
 
B

Bart van Ingen Schenau

Immortal said:
The base class has some data members. Tens of member functions or
hundreds of member functions modify data members.

If you have hundreds of member functions, chances are that your class is
incorrectly designed and does more than one thing.
What if programmer
make mistakes? They might assign incorrect value to the data
members. Then, they have to examine all tens of member functions or
hundreds of member functions to try and locate incorrect values.

If the programmer makes a mistake, then the unit-test of the function
containing the mistake should fail, giving a very direct indication
where to look for the problem.
They
waste their time. They have difficulties to find a bug.
Set and Get member functions are the answer. They can guard against
incorrect value in the data members.

No. setters/getters are not the answer, because they solve the wrong
problem. Members of a class can bypass the setters/getters any time they
want and the outside world has no business to know how a class
internally stores its data.

If you have an Engine class, that class should NOT have getters/setters
for each of the parts that make up the engine, such as pistons and
valves. Instead, the class should provide the users with a few high-
level functions, such as start(), stop(), getRevolutions(),
accelerate(), etc. Each operation corresponds to a basic operation of an
engine, regardless of how it is internally represented.
The programmers do not have to
examine all member functions. They can only locate set or get member
function before they can easily correct incorrect values. It saves
more time.

Experience tells me that it does not save time at all.
Most errors are found by review or unit testing, where it is known
exactly which function is causing the wrong value to be written.
If the bug escapes that level, then it is almost always not a single
value that is wrong, but a combination of (individually valid) values
that is wrong as a combination (think about things like the date 30 Feb
2009). With such a problem, inspecting setters for single values is not
going to help. On the other hand, there is also no need to examine all
the member functions. Based on the situation where the error occurs, you
can usually narrow the search down to no more than a hand-full of
functions.
Can C++ Compiler inline set and get member functions to improve
optimization? Then data members should be set to private.

Data members should be set to private anyway. Only if there is a special
reason to allow derived classes access to them, could some data members
be declared as protected.
Set and
Get member functions will be inherited into derived class.
Please take a look at my code. It gives you some ideas. Tell me
your opinion. Is it worth best C++ practice?

No, exposing data members (either directly or through getters/setters)
is certainly NOT a best practice.

<snip - code>

Bart v Ingen Schenau
 
J

Juha Nieminen

Immortal said:
Tens of member functions or
hundreds of member functions modify data members.

I'd say that if you have tens or even hundreds of accessor functions,
your class design is flawed.

The general principle of class design is that its public interface
should *abstract* away the actual internal implementation of the class.
In other words, in an optimal case, one should not be able to deduce
from the public interface alone what kind of member variables the class has.

Explicit variable getter and setter functions somewhat break this
principle, as they expose the internal structure of the class. Of course
it's better than having the member variable in the public interface
directly, but it's still often a sign of flawed design.

This isn't a hard rule, of course. There are some situations where
explicit getters and setters are justifiable. However, it's a good
generic principle. Also, in general, the more explicit getters and
setters you have in a class, the more it is a sign of bad design.

As an example, consider the size() member function of the STL data
containers. Is it a getter function? In fact, it isn't: It's simply a
function to query the data container for the amount of elements stored.
It *might* be a direct getter for a member variable, but it might very
well not be (eg. many std::vector implementations don't have any
explicit size member variable, and instead size() returns the difference
between end() and begin()).

When you want information out of a class, the functions to query for
that information should be at a slightly higher abstraction level than
"return me the value of this member variable of yours".
 
J

Jorgen Grahn

Yes, and you've actually done it by defining the getters/setters in
the class body. See

http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.8

and also the FAQ just before it.

And also note that this is so basic C++ that the fact that he needs to
ask means he should probably spend more time studying the language, in
books.
I prefer not to pollute the class declaration with function bodies. I
think that's the prevailing opinion as well.

I prefer that too, but ...
Getters and setters
aren't usually a drag on performance.

.... inlining a simple function like that is such a huge boost, not in
clock cycles but relatively -- you replace a function call and the
cost of not knowing (at the calling point) what happens inside it,
with probably just one assembly instruction.

Maybe it has more to do with my psychology, but I prefer to do it, and
then I never have to think about it again. It doesn't matter if I call
it once a day or once per nanosecond.

/Jorgen
 
J

James Kanze

Or even a couple!

It depends. The role of some classes is to represent specific
data. In such classes, almost all member functions would be
getters and setters (under some name or another). But of
course, no reasonable data container class will have hundreds of
members. And you wouldn't normally use getters and setters for
accessing data from another member function; only from the
outside.
 
J

James Kanze

Immortal Nephi wrote:

[...]
If you have an Engine class, that class should NOT have
getters/setters for each of the parts that make up the engine,
such as pistons and valves. Instead, the class should provide
the users with a few high- level functions, such as start(),
stop(), getRevolutions(), accelerate(), etc.

Even if the class represents something that your factory
manufactures? Where you never "start" or "stop" the engine, but
you do need to have the parts list in order to determine what
you have to order in order to start fabrication.

[...]
Data members should be set to private anyway. Only if there is
a special reason to allow derived classes access to them,
could some data members be declared as protected.

Again, there are exceptions. In general, all data members
should be private, but there are types of classes (in my
experience, mostly nested private classes, but not only) where
it makes sense for all data members to be public. Anything but
all public or all private, however, is very rare.
 
D

Daniel T.

... exposing data members (either directly or through
getters/setters) is certainly NOT a best practice.

A member-function that returns state information about an object is
*not* exposing data members. A member-function that changes the state
of an object in some defined way is also not exposing data members.

As a simple example:

class Range {
// private stuff
public:
// invariant: low() < high()
// invariant: high() - low() == distance()
int high() const;
int low() const;
int distance() const;
void setLow(int v);
void setDistance(int v);
};

No data member's are exposed in the above getters/setters.
 
J

Jorgen Grahn

....


If the programmer makes a mistake, then the unit-test of the function
containing the mistake should fail, giving a very direct indication
where to look for the problem.

Trying to "lock down" the code is IMHO a good thing in general. You
wouldn't recommend unit tests instead of static type checking, right?

I agree about setters and getters, but I think it's dangerous to wave
the unit test card too often. Before we know it, we may all be
programming in Python ;-)

/Jorgen
 
J

Jorgen Grahn

It depends. The role of some classes is to represent specific
data. In such classes, almost all member functions would be
getters and setters (under some name or another).

At that point I often break down and call it a struct with public data
members (but with well-defined construction and copy semantics).

One thing which helps a lot is if these data members are real,
distinct types. If I encounter a

struct Foo { int a, b, c; };

my first reaction is *not* to add set/get methods. Instead I look
at a, b and c and try to find out if they can't be made something
more type-safe than just an int. Maybe a and b together really
form a distinct type, and so on.

I think tiny, concrete types are underused in much C++ code.
Maybe too many programmers come from Java, where there is a
performance penalty for anything more complex than an int.

/Jorgen
 
J

James Kanze

At that point I often break down and call it a struct with
public data members (but with well-defined construction and
copy semantics).

I tend to call it a structure as well. But as far as C++ is
concerned, it is a class, even if I declare it with the keyword
'struct'.
One thing which helps a lot is if these data members are real,
distinct types. If I encounter a
struct Foo { int a, b, c; };
my first reaction is *not* to add set/get methods. Instead I
look at a, b and c and try to find out if they can't be made
something more type-safe than just an int. Maybe a and b
together really form a distinct type, and so on.

That's not a bad policy, in general. (It would be even better
if we has a variant of typedef which created a new type.) But
it's not always applicable, and in some cases, even if it could
be applicable, it would be overkill; you wouldn't really want
complex to be anything but two floating point types. And third
party interfaces have to be considered: the data base interface
will readily accept ints, but will probably bawk at your own
special type.
I think tiny, concrete types are underused in much C++ code.
Maybe too many programmers come from Java, where there is a
performance penalty for anything more complex than an int.

I agree with you there, but I won't go to the other extreme
either.
 
B

Bart van Ingen Schenau

Jorgen said:
Trying to "lock down" the code is IMHO a good thing in general. You
wouldn't recommend unit tests instead of static type checking, right?

No, I would not. Just like I would not recommend replacing making a
design or code reviews with unit testing.
I agree about setters and getters, but I think it's dangerous to wave
the unit test card too often. Before we know it, we may all be
programming in Python ;-)

Then we are in agreement :)
Bart v Ingen Schenau
 
J

Jorgen Grahn

A member-function that returns state information about an object is
*not* exposing data members. A member-function that changes the state
of an object in some defined way is also not exposing data members.

As a simple example:

class Range {
// private stuff
public:
// invariant: low() < high()
// invariant: high() - low() == distance()
int high() const;
int low() const;
int distance() const;
void setLow(int v);
void setDistance(int v);
};

No data member's are exposed in the above getters/setters.

But the setters can be used to break the invariant -- something I
associate with getters/setters. (Unless setLow() throws, but that
is probably not a good idea.)

How about:

void Range::include(int n); // widen range to include 'n'
// can't come up with an interface for shrinking it

(Of course, this is just an example, and we don't know what
it is supposed to be used for.)

/Jorgen
 
B

Bo Persson

Jorgen said:
But the setters can be used to break the invariant -- something I
associate with getters/setters. (Unless setLow() throws, but that
is probably not a good idea.)

Or setLow could (perversely) also move High as needed to preserve the
distance invariant. Who knows? There isn't a setHigh anyway.
How about:

void Range::include(int n); // widen range to include 'n'
// can't come up with an interface for shrinking it

(Of course, this is just an example, and we don't know what
it is supposed to be used for.)

No, that's most often the problem with made-up examples. :)


Bo Persson
 
G

Gerhard Fiedler

Jorgen said:
But the setters can be used to break the invariant

Doesn't this depend on the implementation? If there's an invariant,
shouldn't the setter of a decent implementation maintain it? I'm sure
most programmers can come up with four different implementations for the
above class that don't violate any of the documented invariants.

Gerhard
 
J

James Kanze

I agree with this, however I rarely find a type containing
only one member-variable useful. :)

It depends. I've a counter class, which is nothing more than an
int which takes care of initialization and overflow detection
(and doesn't support anything but ++ and --). I also use
std::auto_ptr some, and a typical implementation of it will only
contain a single member variable. I'd probably use a lot more
such classes if they didn't require so much effort to write; I
know that some people have developed complet sets of SI units,
to ensure coherence (e.g. multiplying meters by meters gives
square meters, and not just meters).
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top