|
-
July 21st, 2004, 03:43 PM
#1
setter and getter vs. public members
This is kinda related to my other thread about protected members.
If I have a data member, maybe an int val which should be readable as well as writable by clients. Is it still better practice to create a getter AND setter method instead of making the member public?
- Matthias
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup
-
July 21st, 2004, 04:00 PM
#2
If an object is fully accessible to anyone anywhere, then what is the point
of initialization during construction?...
Using a public member is using a global (in terms of accessibility) which
collides C++ encapsulation.
**** **** **** **** **/**
-
July 21st, 2004, 04:15 PM
#3
I don't get your point. It's not global, it's still in the context of the class.
- Matthias
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup
-
July 21st, 2004, 04:36 PM
#4
An object instance allows everyone to "mess" its public member, like a program that allows everyone to "mess" its globals.
**** **** **** **** **/**
-
July 21st, 2004, 05:38 PM
#5
Guysl's point is that it's globally accessable, i.e. accessable by anyone in the (program) world. The problem with this approach is that the class itself then has no way of knowing that someone has changed it's variable(s) which can lead to disaster. I believe that there was an example posted, something like this:
Code:
class foo
{
public:
foo() { m_MyData = new char [100]; }
~foo() { delete [] m_MyData; }
void doSomethingWithData(const char *pNewData)
{ strcpy(m_MyData, pNewData); }
char *m_MyData;
};
int main()
{
foo myFoo;
myFoo.m_MyData = NULL;
myFoo.doSomethingWithData("This will crash!!!");
}
This is bad. Since it's my data, I'm assuming that the data will be valid for the life of the class instance. However, because the data is public, anyone can change it, and cause crashes, memory leaks, etc...
Now, if the data was private, then only my class can change it. Therefore, I can completely control when it's created/deleted, etc.
Viggy
-
July 21st, 2004, 05:54 PM
#6
Public setter and getter (for a private member), compared to a public member variable, are similar in access rights, but have a significant difference: setter (and getter) provide extra layer of abstraction.
A few of the benefits are:
- controlled access (optional validation, counters, etc.)
- notification of a change (obviously), so you can update related data
- hiding implementation details (you can change a type of that member, or even combine it with another or split into multiple members), without changing client's code
Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
Convenience and productivity tools for Microsoft Visual Studio:
FeinWindows - replacement windows manager for Visual Studio, and more...
-
July 22nd, 2004, 02:17 AM
#7
It's a matter of style. When they implemented std::pair they made it a struct (which is the same as a class anyway). So you use aPair.first and aPair.second to access rather than aPair.getFirst() and aPair.getSecond().
Generally the rule is that for small data structs it is fine to use public members, usually fairly basic types, but for fully-fledged classes it's slightly more conventional to make the attributes private and use access functions.
While in C++ a class and a struct are the same thing, on a design level, I would call a struct a collection of data - it may have user-defined constructors but not really "methods" as such. A class has attributes rather than data and methods.
get functions are usually inlined and therefore there is no major difference in performance. set functions can be useful for debugging as you can stick a breakpoint or a cout in a set function to trace where it is being called more easily.
-
July 22nd, 2004, 02:33 AM
#8
Alright, thanks, I usually do it like NMTop40 said. Although struct is pretty useless in C++ I use it when I have a small class which has no user defined methods and only data members which are supposed to be accessed by the "public domain" 
And what if I have a class (a nested class for example) that I don't want *everyone* to access a certain setter method, but only the outer class. Then 'friend' and 'private' are the way to go instead of just making the setter public, right?
- Matthias
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup
-
July 22nd, 2004, 02:38 AM
#9
With a nested class I will sometimes put the nested class in the private area of the class but make its access all public, thus giving the outer class full access.
-
July 22nd, 2004, 02:43 AM
#10
 Originally Posted by NMTop40
While in C++ a class and a struct are the same thing...
Well...in general this is correct, however, there are two differences between them...
- By default, the members of a class are private, while the members of a structure are public.
- Structs are inherited from publically by default while classes are inherited from privately.
Aside from these distinctions, structures and classes perform exactly the same function.
-
July 22nd, 2004, 02:48 AM
#11
Yes that is true. I generally think in a class it is clearer to use the keyword "private" anyway though.
-
July 22nd, 2004, 03:18 AM
#12
One thing that could come in handy is the use of a friend function. This could help you get what you want.
-
July 22nd, 2004, 03:59 AM
#13
Friends are iffy in that they greatly increase the coupling in your program, which is something that you generally want to reduce. Indeed, friendship is the tightest coupling there is, followed by inheritance (because friendship grants access to all members, whereas inheritance still denies access to private members).
The thing to keep in mind is the distinction between interface and implementation. A well-designed class will present a good, useful interface to the rest of the world. The implementation of that interface, however, should be hidden. The rest of the program should not be interested in how the class works, only in what it does. By hiding the implementation, you give yourself the freedom to change that implementation at will without affecting the rest of the program. Expose any part of your implementation and you have to be very careful about changing it, because other classes and functions may be dependent on the specifics (IOW, you have high coupling between classes).
Implementation hiding reaches its peak with the pimpl idiom, where the class consists only of public function members and a single pointer to an implementation class:
Code:
class foo
{
public:
// function members
private:
class fooimpl* pimpl;
};
Using this idiom, the entire implementation is hidden away in the implementation file. The outside world only sees a single name (fooimpl), without even a class definition - and even the little bit that can be "seen" is private. The freedom this gives you to radically alter the implementation is unrivalled - you cannot affect anyone else, even if you completely rewrite the implementation. And, since changing the implementation doesn't even affect the header file, a complete rewrite of the implementation still only requires the recompilation of a single file. (Of course, if the new implementation is rubbish, that is a sort of effect, but that's not what I mean.)
The protected section of a class is there to provide an interface for use by derived classes only - it's like the public section apart from restricted access.
This is not about style, this is about clean code, maintainable code, robust code - code that you can muck about with without having the whole edifice collapse around your ears; code that you're not afraid to make improvements to, because you know changes will be localised and easily undone.
My personal approach to the implementation of a class's (public and protected) interface is:
1) Whenever possible, make it invisible (using pimpl).
2) If I can't make it invisible, make it private.
3) If I can't make it private, retire, because I've forgotten how to write C++.
Your mileage may vary, of course. I've described a personal approach, one which comes from viewing C++ classes not as blobs that contain functions and data, but as entities that provide an interface and an implementation of that interface. To my mind, data members are implementation, with very few exceptions (I can't think of one at the moment), so should be hidden from everyone.
Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
-- Sutter and Alexandrescu, C++ Coding Standards
Programs must be written for people to read, and only incidentally for machines to execute.
-- Harold Abelson and Gerald Jay Sussman
The cheapest, fastest and most reliable components of a computer system are those that aren't there.
-- Gordon Bell
-
July 22nd, 2004, 04:46 AM
#14
 Originally Posted by Graham
Friends are iffy in that they greatly increase the coupling in your program, which is something that you generally want to reduce. Indeed, friendship is the tightest coupling there is, followed by inheritance (because friendship grants access to all members, whereas inheritance still denies access to private members).
The thing to keep in mind is the distinction between interface and implementation. A well-designed class will present a good, useful interface to the rest of the world. The implementation of that interface, however, should be hidden. The rest of the program should not be interested in how the class works, only in what it does. By hiding the implementation, you give yourself the freedom to change that implementation at will without affecting the rest of the program. Expose any part of your implementation and you have to be very careful about changing it, because other classes and functions may be dependent on the specifics (IOW, you have high coupling between classes).
Implementation hiding reaches its peak with the pimpl idiom, where the class consists only of public function members and a single pointer to an implementation class:
Code:
class foo
{
public:
// function members
private:
class fooimpl* pimpl;
};
Using this idiom, the entire implementation is hidden away in the implementation file. The outside world only sees a single name (fooimpl), without even a class definition - and even the little bit that can be "seen" is private. The freedom this gives you to radically alter the implementation is unrivalled - you cannot affect anyone else, even if you completely rewrite the implementation. And, since changing the implementation doesn't even affect the header file, a complete rewrite of the implementation still only requires the recompilation of a single file. (Of course, if the new implementation is rubbish, that is a sort of effect, but that's not what I mean.)
The protected section of a class is there to provide an interface for use by derived classes only - it's like the public section apart from restricted access.
This is not about style, this is about clean code, maintainable code, robust code - code that you can muck about with without having the whole edifice collapse around your ears; code that you're not afraid to make improvements to, because you know changes will be localised and easily undone.
My personal approach to the implementation of a class's (public and protected) interface is:
1) Whenever possible, make it invisible (using pimpl).
2) If I can't make it invisible, make it private.
3) If I can't make it private, retire, because I've forgotten how to write C++.
Your mileage may vary, of course. I've described a personal approach, one which comes from viewing C++ classes not as blobs that contain functions and data, but as entities that provide an interface and an implementation of that interface. To my mind, data members are implementation, with very few exceptions (I can't think of one at the moment), so should be hidden from everyone.
Well, yes, you're right. I should have stated that friend functions/classes have to be dealt with care. But it is one example on how the program can get access to a class's variables or functions.
-
July 22nd, 2004, 04:57 AM
#15
Graham, I've read your entire post, but I still have some questions.
When you talk about the pimpl idiom, do you mean something like having 2 classes, one for implementation and one that uses the implementation class but prevents the modification of this class?
Last edited by YourSurrogateGod; July 22nd, 2004 at 05:04 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|