tags:

views:

2912

answers:

12

I notice that get/set is not the c++ way as far as I can tell by looking at boost/stl, and even reading the writings of some of the top c++ experts.

Does anyone use get/set in their c++ class design, and can someone suggest a rule of thumb on where if at all this paradigm belongs in the c++ world?

It is obviously very popular in Java, and imitated by c# using Property syntactic sugar.

EDIT:

Well after reading more about this in one of the links provided in an answer below, I came across at least one argument for keeping the accessors of a member field the same name as the member field. Namely that you could simply expose the member field as public, and instead make it an instance of a class, and then overload the () operator. By using set/get, you'd force clients to not only recompile, but to actually change their code.

Not sure I love the idea, seems a bit too fine grained to me, but more details are here:

C++ Killed the Getter/Setter

+2  A: 

I don't know whether it's recommended usage or not, but I use get/set functions in my C++ classes regularly, and I've been writing C++ code for more than two decades now. I've never looked at Java or C#, so I didn't pick up the habit from those languages.

Head Geek
+1  A: 

I tend to have getters and setters, i just don't tend to call them "getX and "setX", usually i'll do something like this for example:

int x = o->x() // getter
o->setX(5); // setter

i find that having the getter simply be the name of the "property" just reads better.

Evan Teran
In this case, how would you tell an accessor from a method that wasn't an accessor?
Kibbee
Why not only o->x() and o->x(5)?
dalle
@Kibbee:do I really need to be able to tell the difference? Besides, generally it'll either be in the docs or if it truly is just a "getter" it'll be inline in the header,so it'll be obvious. But I don't really see why I *need* to distinguish a getter from other types of methods that return a value.
Evan Teran
@dalle: just a matter of style I suppose. I don't care for having a getter and setter have the same function name.
Evan Teran
@Kibbee: also, if it's a getter, i'll almost certainly be assigning its result to a local or passing it to a function. Which makes it fairly obvious.
Evan Teran
+9  A: 

C++ does not have properties like java and .NET. It is possible to write methods with "get" and "set" in the their names, but they don't automatically create properties. So is it good practice to use get and set methods then?

Using get and set methods in C++ is not bad for accessing class properties. The STL and boost (which was influenced by the STL) just chose one design -- it's perfectly fine to have a different design for your classes.

At my job, we do use get and set. The reason is primarily that it makes it possible to write parsers to automatically wrap the C++ classes by other interfaces -- ActiveX, .NET, LabVIEW, Python, etc.... When using Visual Studio's intellisence (and similar technologies on other IDEs), I find that using get and set methods makes finding what I was easier. So there are times where it is benefficial to use get and set methods.

The most important thing is to choose a code style standard for your library and be consistent with it.

Uhall
+5  A: 

In general get/set methods subvert encapsulation by exposing internal implementation and state. If you find yourself using get/set on every single piece of data in your class, most likely it is better to just make it a simple aggregate type with only public data and no methods.

I don't really buy that get/set makes it easier to do things like, for example make your class thread-safe, because the limited synchronization you can provide protects against all the wrong kinds of race conditions.

Greg Rogers
Get and set do not have to expose internal implementation and state. At my job for example, we use FIR digital filtering. The internal coefficients used are very different than what people specify -- which usually is the breakpoint for a low pass filter. The get and set methods are perfect ...
Uhall
... for making the filters easy to understand for users while still hiding the implementation details. So, I disagree with the generalization in your first sentence, but I do agree that get and set methods *if overused* can subvert encapsulation.
Uhall
In your example, the get/set methods themselves work on sensible logical values, and aren't tied directly to the underlying representation. This is a perfect example of exactly what you want to do, thanks.
Greg Rogers
+4  A: 

Encapsulation is an OOP concept and it applies to all OOP languages. Public data members would break encapsulation. This may be fine if you have a very simple object which does not need encapsulation, however those situations are the exception and once you make the decision it can be hard to go back and undo it.

For most objects you will want to have getters and setters but you should always consider how the object will actually be used when you write them. Boost and STL are full of getters and setters, they just do not use the names "get" and "set" instead they use names like "length," "end," "reserve," "capacity," etc. The reason they do not use the words get or set is because these functions serve a purpose greater than just setting a value in the object.

Your getters and setters should do the same. Instead of designing the interface in terms of how an object works you should define it in terms of how it will be used.

Bernard
A: 

My experience is through C++ and Java, though nowadays I'm working in PHP. My general rules of thumb that I use for PHP and C++ are:

  1. If you need to have a member variable be readable from outside the class but not writable: use getVariableX() only.

  2. If you want to allow member variables to be altered/read outside of the class, but need additional work performed on them before/after their values are changed: use setVariableX() and getVariableX().

  3. If a member variable can be altered from outside the class and the set/get methods would just be simple assignment: just make the variable public, as that's what you would be doing anyway with set/gets (just in a more obfuscated way).

Note that if your get and set methods are doing much more than trivially getting and setting, then you should probably rename them to more accurately describe their function.

Wickethewok
You mean "getVariableX()" in rule #1.
aib
Quite right - fixed. Thanks!
Wickethewok
A: 

I only use getters/setters when there is no alternative. When I can, I use this pattern (not in the sense that it's a good practice, but in the sense that I do this consistently): Changing a property doesn't affect the object's behavior until it is really needed. For example:

myWnd->Title = "hello"; // not a setter, just a LPCSTR member
myWnd->Title = "world";
myWnd->ShowWindow();    // perhaps updates a WNDCLASS structure
                        // and other complicated things that
                        // the user of the class doesn't want to know

I know this means I will have to write some contrived private methods to update objects' internal states, but if that effort is needed to hide the complexity to the class user, I will have to make it.

Eduardo León
I think your code sample pinpoints the most useful case for public setter methods. ShowWindow, along with every any other method that accesses the Title field, is going to have to at least check that Title is still sane. What if it's a megabyte long? What if it's a zero length string? What if it's a null pointer? Instead, use setter methods to maintain the class invariant. Setters can fail fast, and tell you where your real logic problem is.
Daniel Yankowsky
The designer of the class must define all the necessary validators as private methods. If a condition you don't want happens (e.g. the title is a megabyte long), either the validator should raise an exception or the public method should return an error flag.
Eduardo León
+3  A: 

You can definitely use accessors in C++. This is a good article on coming up with good accessor schemes. A related article also shows you a simple meta accessor helper class to help you define these smart accessors trivially.

ididak
A: 

I'm going to take some guesses.

  • C did't even have the possibility of getters/setters, so there was a habit of using direct access to members, as in a struct. The habit stuck in C++.
  • C/C++ have always favored speed, and if there was any possibility of an old compiler that wouldn't properly inline, a getter/setter would have a speed penalty.

Neither of these are compelling reasons.

Mark Ransom
Getter/Setters can be implemented in C - it just takes some discipline to adhere to strict encapsulation of objects. Something like the pimpl idiom can be used in C to help. If you look at the std lib's FILE APIs, you might consider ftell() and fsetpos() as getter/setter for the FILE's position.
Michael Burr
The reason that in-class defined methods are implicitly "inline" is exactly because that feature was deemed important for getters/setters. So, even old compilers were strongly expected to inline getters/setters
MSalters
+1  A: 

I almost always use get/set methods, mainly because you can set breakpoints on them and find out where a data member is being set (or accessed, though this is less common). Also, you can add debug assertions inside the setter routine (and the getter routine, though this is less useful) to make sure the object is in a valid state when setting the value.

It's also useful if you create a subclass; sometimes the subclass wants to do some calculation rather than just retuning the value. Making the getter routine virtual and then overriding it in the subclass makes this easy.

Graeme Perrow
+1  A: 

Going to be a bit didactic here...

There are two aspects to accessors:

  • Working within the syntax of the language
  • Communicating intent

There's also a third aspect that is often ignored, and that is to do with handling change gracefully. My article you link to addresses this last point, but doesn't tell you anything about the other two.

To try to handle change within the syntax of the language you're using is mostly a technical issue, one which is amenable to a few tips thrown together on a web page with a bit of code to back it up.

The hardest aspect is communicating intent and the way to do that is to stick with the idioms of the language. Unfortunately in C++ the syntax gets in the way of this somewhat so we have things like .size() on collections and .first and .second on pairs. They're all accessors, but the syntax changes depending on the implementation -- ouch.

Now, eJames talks about public members breaking encapsulation. Whether a member is public or not has nothing to do with encapsulation. Encapsulation is a product of the design of the objects and of the controls available to the class designer within the language they're using. This is something I explored in a bit more depth in "Encapsulation is a Good Thing™" (this site won't let me add a link yet, but I guess it isn't too hard to Google).

What this leaves us with is that in C++ a derived attribute must use method invocation syntax. A non-derived field doesn't have to, but may choose to if you so wish. If you do use method invocation syntax then you have to write the wrapper method yourself. Not difficult, but it certainly adds to the line count. What I tried to show was a way to use the C++ template language to abstract out the accessor code. It's not totally successful, but it does handle many use cases.

As for whether we should use accessors or not, the problem is that C++ syntax forces the distinction between plain member access and method access upon us as developers. This is annoying, but we do have some tools to do something about it.

As a library developer I've found that always using method invocation syntax helps me to build more robust APIs because if I find that I want to replace a plain member with something more complex then it gives me more options that don't require quite so much syntax. Remember, I could abstract the other way and make a "function" look like a value by suitable use of cast operators and assigment operators -- actualy maybe I'll try that out and see how I feel about it :)

KayEss
A: 

Even tho c++ doesnt support property accessors by simulating them we dont only make readibility better or provide encapsulation but we provide control mechanism to set a value to a variable or we get calculated value for a variable. So this is the ultimate purpose of accessors. To achive these goals language doenst necesserily support accessors directly. Period.

Cengiz