Fog Creek Software
Discussion Board




C++ and accessors--what's the deal with the names?

Yeah, I know this has come up over and over again here, but I'm curious about one particular aspect of this issue.

How come people *always* create accessor methods with names that start with "get" and "set"? For example:

char *username = user->getUsername();
...
user->setUsername(username);

C++ allows you to overload routines, creating multiple ones with the same name that get called in different ways, so how come no one ever seems to use this for accessor methods? For example:

private:
  char *_username;
...
public:
  char* username(void);
  void username(char*);
...

username = user->username();
...
user->username(username);

That's how you'd do it in Smalltalk or Objective-C, so why not in C++ too? Why is this so scarce? Is it because people think overloading is always bad, regardless of whether you're overloading an operator or a routine? Is it because doing so forces you to rename the member variable to stop it from colliding with the accessor methods baring its name (e.g., add a leading underscore to it like I did)? Is it just because that's how developers are used to doing in C, where you have no overloading?

Messed up by Aspertame
Friday, June 11, 2004

Objects (classes) are usually nouns (things), and methods are usually verbs.

I'd prefer to read either "username = user->username", or "username = user->get_username()".

So, perhaps the answer to your question is "because C++ doesn't support C#-like 'properties'".

Christopher Wells
Friday, June 11, 2004

When you read the code does one read better
than the other?

Often instead of using the type char* you will use
a class instead. Like object->username(const  Username& name). The code gets confusing at this point.

Often on a get, an object is passed in rather
than returning an internal object or allocating a new
one. Then the signatures differ by a const, which is
confusing.

When searching and you want to search to find all your
gets, for example, if the names are the same it is harder
to search for.

I also recall that at one much earlier time a method name
and class name could conflict.

son of parnas
Friday, June 11, 2004

Exactly, a C++ developer would probably read user->username() as instantiating an instance of something.

The ATL COM wrappers do allow "properties" in interface definitions, but you have to implement it with get_ and set_ prepended to it in the C++ class.

Larry
Friday, June 11, 2004

Having to write trivial getters and setters in the first place is just another of the ugly tedious little hoops C++ makes you jump through anyway, IMHO. Likewise copy constructors, operator=, etc etc. Just long lists of busy-work you have to do to make even a basic class behave in a safe flexible appropriate manner.

"I invented the term Object-Oriented, and I can
tell you I did not have C++ in mind."
-Alan Kay

Matt
Friday, June 11, 2004

> Having to write trivial getters and setters in the first place is just another of the ugly tedious little hoops C++ makes you jump through anyway, IMHO.

If it's genuinely trivial you don't need a getter/setter method: instead you just make the data member public.

> Likewise copy constructors, operator=, etc etc. Just long lists of busy-work you have to do to make even a basic class behave in a safe flexible appropriate manner.

C++ generates a default copy constructor and assignment operator for every class: which generally does the right thing, unless your class contains a C-like pointer (instead of containing, for example, a C++-like smart pointer).

Christopher Wells
Friday, June 11, 2004

I write getters/setters in the way that you described.  Like the previous poster said, it's usually a crappy thing to have to do, but in some cases it's necessary.  In my window abstraction library, for example, my window class has  const std::string& Title() const; and void Title(const std::string& s); methods.

Kalani
Friday, June 11, 2004

>> C++ doesn't support C#-like 'properties'

I was amazed to discover that Visual C++ does, with __declspec(property)


private:
    char* m_username;

public:
    char* getUsername() { return m_username; }
    void setUsername(char* name) { m_username = name;  }

    // this is the magic
    _declspec (property(get=getUsername, put=setUsername)) char* username;


And in code:

User.username = "Jack"; // calls setUsername()
char* name = User.username // calls getUsername()

You can do neat things like read-only (and write-only!) properties, without all the ()s.

Of course it's MS specific, but what else is out there anyway ? :D

Alex
Friday, June 11, 2004

>> In my window abstraction library

My gosh, Kalani, you *too* have a window abstraction library? :)

Alex
Friday, June 11, 2004

Yeah, I know you can often get away without them, the books always seem to make out like its a horendous crime not to implement copy constructors, getters and setters etc though.

operator= just does a bitwise copy by default doesn't it? Feel like that'd be undesirable in a lot of occasions. I've been doing all my OO stuff in python recently which is much nicer, making references unless you specifically ask it to copy something :)

Getters and setters feel like something a language with aspect-oriented features would make redundant...

Matt
Friday, June 11, 2004

"Properties" while sometimes necessary, they are often the residue of a poorly thought our design.

Properties SHOULD look ugly because they are ugly.  People that overuse them are ugly.

Rather than thinking about how an object might reside on its own and have well defined characteristics, you get property SPLAT:

property_set( XYZ_SPECIAL_CASE, 1 );
property_set( ABC_BOSS_WANTS, 0 );

It should be ugly, because it is.

hoser
Friday, June 11, 2004

> operator= just does a bitwise copy by default doesn't it?

Doesn't it invoke operator= on each member? Which results in bitwise copy of POD (plain old value data) members, or the user-defined operator= for members that are classes with a user-defined operator= (for example, for members that are smart pointers).

Christopher Wells
Friday, June 11, 2004

Oh ok. That's a bit nicer. It's a while since I've done any C++ as you can probably tell...

Matt
Friday, June 11, 2004

You can't guarantee what it calls on each member.
I had a class with some char[] members but they contained
byte values with 0s in them.

On one compiler the default copy constructor decided to call strcpy() on each of these members instead of memcpy()
and so copied only upto the first 0.

Martin Beckett
Friday, June 11, 2004

> You can't guarantee what it calls on each member.

Is that true? Or was that a compiler bug?

> That's a bit nicer.

Yes. So if you don't have dumb pointers (if you only have smart pointers) then you don't need to define the copy ctor and the assignment operator (and, if you're using exceptions you might want to use smart instead of dumb pointers anyway, to be exception-safe).

So, usually, when I do declare them, it is only to disable them (by declaring them as private and commenting that they're undefined/unimplemented).

Christopher Wells
Friday, June 11, 2004

I use getX() to distinguish it from, say, makeX(), which makes a new object X.

You want to remove 3 characters -- and arguably 3 chars that make code easier to read -- simply to make things shorter?  Gah.

(C++ is not smalltalk.  If you want Smalltalk, you know where to find it.)

Wally
Friday, June 11, 2004

> It should be ugly, because it is.

Objects have state. I wish java and C++
had properties because things have properties.
Wishing it weren't so doesn't help.

son of parnas
Friday, June 11, 2004

>Objects have state.

That doesn't mean that they have to let it dangle out.  You've got 'private parts' yourself, but that doesn't mean that you expose them to everybody on the street.

Kalani
Friday, June 11, 2004

>'private parts' yourself, but that doesn't mean
>that you expose them to everybody on the street.

If i have exposed them then by definition they
aren't private. We are talking about public state
that i want people to have access to. Like an empoyee
object returning an employment start date. Unless
you think i should go around zipped up in a
sleeping bag?

son of parnas
Friday, June 11, 2004

Random observations......

1. Public member variables are a crime againest humanity.
2. Massive amounts of Get/Set type action usally means you have the wrong level of abstraction.
3. Overloading Get/Set functions to have the same names makes code hard to read.
4. If the class is non-trivial you probably should be preventing copying from happening (boost::noncopyable), else compiler generated copys should be sufficent.
5. You should be using std::string instead of char[].

Craig
Friday, June 11, 2004

I think the reason people don't do this is because you don't use the same name for two methods that do two totally different things.

Tom
Friday, June 11, 2004

Living in the slowly fading fields of Delphi, it never occured to me that mutators could take more than a new property value and maybe an index (Delphi does not allow that sort of thing).

Something like that is not really a mutator: it is a procedure that has the side effect of setting the property value. Mutators either accept the value (and perform side-effects and notifications) or reject the value because it is illegal or incompatible with the current state of the object.

Cheers

Richard C Haven
Friday, June 11, 2004

son of parnas,

I've used methods like that too so I actually agree with you in some sense.  Still, I've found lately that property bags for things like user objects (really anything with more than a few properties) are more useful because the structure of those things changes often, and you can preserve the semantics of older structures pretty easily if that's necessary.

Kalani
Friday, June 11, 2004

<i>
You've got 'private parts' yourself, but that doesn't mean that you expose them to everybody on the street.
</i>

Speak for yourself, prudie.

Mr. Fancypants
Friday, June 11, 2004

Christopher:

"Yes. So if you don't have dumb pointers (if you only have smart pointers) then you don't need to define the copy ctor and the assignment operator"

Why do you say that? Actually, if you had std::auto_ptr<T> member in your class and if you let the compiler do its thing, it could be disastrous.

Even if you had something like boost::shared_ptr<T>, you might want to control how copies are made.

SKV

SKV
Saturday, June 12, 2004

I like the concept of getXXX() and setXXX().

My only complaint is that they differ by a single letter, a bad way of naming methods (or variables, or functions in non-OO code).

One place I worked, there were two Boolean globals (!) named sendToFormatter and sentToFormatter.

The first, if true, meant the active record needed to be sent to the formatting module, the second, if true, that the record had been sent to the formatter. This similarity of naming caused no end of confusion. Of course the people who had been their 10 years knew the difference. Why not name the flags recordNeedsFormatting and recordIsFormatted instead, less symmetrical but clearer what's going on.

These are symptomatic of a certain "cuteness" which infects programming and especially the academic world of computer science. The love of puns and verbal flash is all very nice at the dinner after the weekly seminar, but it's not so good when the CTO is doing a pretty good imitation of Ming The Merciless and it's 2:30 Sunday morning and you've been working for 50 hours straight and the release date is Monday morning and the damn thing still isn't working.

frustrated
Sunday, June 13, 2004

>> the CTO is doing a pretty good imitation of Ming The Merciless

Sorry, couldn't resist, but LOL.

Alex
Sunday, June 13, 2004

*  Recent Topics

*  Fog Creek Home