Thread: [Dev-C++] public/private data decision
Open Source C & C++ IDE for Windows
Brought to you by:
claplace
|
From: <or...@vp...> - 2004-04-12 20:24:52
|
Hi! I have been pondering on this for quite some time, but it seems I cannot=20 get myself to a firm decision. Suppose I have a class, which has some data. Mostly string data. Like=20 name, path, etc. Uptil now I always put these things into the private=20 part of my class, and I provided Get/Set methods for accessing them. I ask: does it worth the extra overhead? I mean, what if I simply put=20 the data into the public section, and then I have 2 (or more) member=20 functions less, and the same access to the data. Can someone with more experience with C++ give some guidelines to me=20 about this. Posting personal experience would be the best! Thank you. -- Greetings, Bal=E1zs |
|
From: <or...@vp...> - 2004-04-12 22:00:34
|
Hi! Thanks for both of your comments, they were indeed really helpful! Actually, I was thinking about the same, that "data-storage" like=20 classes, where I don't need to check for anything special (no=20 invariant), there is no need for get/set methods, I was just in doubt,=20 which leads me to my next question: What should count as an invariant? Suppose I have some class, which=20 stores a file-path internally. There is a method: Save (saves the=20 object). Should the path always be valid? Or should Save throw an=20 exception if it cannot open the file for writing? Or both? Because if I look at it the second way, there is no need for the get/set=20 stuff, as Save will check the path anyway. Any comments? (The above is just a very simplified example) I'll look for Stroustrups's writings what you mentioned, BTW. -- Greetings, Bal=E1zs |
|
From: <or...@vp...> - 2004-04-12 23:01:05
|
Krzysztof Kapuscik wrote: > BTW. Throwing exceptions are sometimes not best way to inform that > something has not gone the right way. Sometimes (often?) it is better > to return bool (success/failure) or int (0=3Dsuccess, <>0 error code) > value. Yeah, I first used that, but this time I need exceptions, as there is=20 some inheritance involved, and not only one thing is saved, but several=20 Save's are called, and doing: if ( c1.Save() ) if ( c2.Save() ) if ( c3.Save() ) return true; else ... became too painful :) But for simple cases, returning bool would be absolutely fine! Thanks for your comments! -- Greetings, Bal=E1zs |
|
From: <or...@vp...> - 2004-04-13 09:24:10
|
Krzysztof Kapuscik wrote: > But for above example you could use: > return (c1.Save() && c2.Save() && c3.Save()); >=20 > Just remember (yeah, I know you remember this) that && operators are > evaluated as long as there is 0 value as operator argument, so if > you'll get c2.Save() =3D=3D false then c3.Save() will never be done (fo= r > all standard complaint compilers - if I good remember, I'm not so > sure, 'cause it is 1:38 AM in my time zone ;) ). Yes, it is ANSI standard, the shortcut-evaluation, already present in C. I have been reading here and there about this public-private stuff, but=20 still, there are very diverse styles. I have read this somewhere: -- Class variables should never be declared public. The concept of C++ information hiding and encapsulation is violated by=20 public variables. Use private variables and access functions instead.=20 One exception to this rule is when the class is essentially a data=20 structure, with no behavior (equivalent to a C struct). In this case it=20 is appropriate to make the class' instance variables public [2]. Note that structs are kept in C++ for compatibility with C only, and=20 avoiding them increases the readability of the code by reducing the=20 number of constructs used. Use a class instead. -- It states that use public data ONLY if the whole thing is a data class=20 (a struct). But what if there ARE a few methods present for the class,=20 but mostly, it contains data? Another question: I used the m_ (or simply m) prefix for variables in a=20 class, and they were mostly private or protected. What if I put the data=20 into the public section? Should I still use this (or other) prefix for=20 those too? (I don't use any other prefixes. Though I'm Hungarian, I DON'T use=20 Hungarian-notation :) -- Greetings, Bal=E1zs P.S.: Maybe i spend too much time pondering on unimportant things... |
|
From: Daniel K. O. <dan...@ya...> - 2004-04-13 09:59:00
|
OROSZI Balázs wrote: > It states that use public data ONLY if the whole thing is a data class > (a struct). But what if there ARE a few methods present for the class, > but mostly, it contains data? I tend to agree with Sroustrup: From http://www.artima.com/intv/goldilocks3.html > *Bjarne Stroustrup*: My rule of thumb is that you should have a real > class with an interface and a hidden representation if and only if you > can consider an invariant for the class. > What should count as an invariant? Suppose I have some class, which > stores a file-path internally. The follow up of the interview: > *Bill Venners*: What do you mean by invariant? > > *Bjarne Stroustrup*: What is it that makes the object a valid object? > An invariant allows you to say when the object's representation is > good and when it isn't. Take a |vector| as a very simple example. A > |vector| knows that it has n elements. It has a pointer to n elements. > The invariant is exactly that: the pointer points to something, and > that something can hold n elements. If it holds n+1 or n-1 elements, > that's a bug. If that pointer is zero, it's a bug, because it doesn't > point to anything. That means it's a violation of an invariant. So you > have to be able to state which objects make sense. Which are good and > which are bad. And you can write the interfaces so that they maintain > that invariant. That's one way of keeping track that your member > functions are reasonable. It's also a way of keeping track of which > operations need to be member functions. Operations that don't need to > mess with the representation are better done outside the class. So > that you get a clean, small interface that you can understand and > maintain. > Ando this: > *Bill Venners*: The invariant is a relationship between different > pieces of data in the class. > > *Bjarne Stroustrup*: Yes. If every data can have any value, then it > doesn't make much sense to have a class. Take a single data structure > that has a name and an address. Any string is a good name, and any > string is a good address. If that's what it is, it's a structure. Just > call it a |struct|. Don't have anything private. Don't do anything > silly like having a hidden name and address field with |get_name| and > |set_address| and |get_name| and |set_name| functions. Or even worse, > make a virtual base class with virtual |get_name| and |set_name| > functions and so on, and override it with the one and only > representation. That's just elaboration. It's not necessary. > So, (I think) your class is no more than a struct (with all data public), and methods to do stuffs with it. Daniel K. O. |
|
From: <or...@vp...> - 2004-04-13 11:09:33
|
Hi! Hey, thanks Krzysztof! Your comments were really helpful. After reading you comments, and Bjarne's talks, I now think how I should=20 decide. Thank you everyone, who helped me out! One more note about the Hungarian notation: m_ and sm_ prefixes are not actually part of the Hungarian notation.=20 Hungarion notation is like this: pstrName szAddress etc. I think that's a bit stupid, but m_ and that kind of stuff IS useful.=20 Here is a very good (a bit sarcastic) writing from the C++-FAQ Lite: ... If you have a Microsoft Windows background, you probably prefer the=20 "Hungarian" style which means you jkuidsPrefix vndskaIdentifiers ncqWith=20 ksldjfTheir nmdsadType... -- Greetings, Bal=E1zs |
|
From: Daniel K. O. <dan...@ya...> - 2004-04-12 22:27:06
|
OROSZI Balázs wrote: > Suppose I have a class, which has some data. Mostly string data. Like > name, path, etc. Uptil now I always put these things into the private > part of my class, and I provided Get/Set methods for accessing them. > I ask: does it worth the extra overhead? I mean, what if I simply put > the data into the public section, and then I have 2 (or more) member > functions less, and the same access to the data. > > Can someone with more experience with C++ give some guidelines to me > about this. Posting personal experience would be the best! I recomend you to go search on Stroustrup's website for his interviews. I remember he answering your questions. It was almos like this: if you need to keep an invariant (like the rules about your data, to make sure it's always valid) then you have a class, with private members and set/get methods. But if all you need is to group the data togheter and there's no special invariant to take care of, you actually have a plain struct, and probably there's no need to the get/set methods. Stroustrup is (obviously) much more objective than me, so better read what he said about this. :) Daniel K. O. |