|
Klaim
|
 |
« Reply #45 on: June 25, 2012, 09:07:08 PM » |
|
I can't remember if C++ is case-sensitive or not 'cause I work in C#, so this might be totally bogus, but this is how i'd get around the accessor-member name clash:
class Foo { private: string name; public: string Name() { return name; } void Name( string newName ) { name = newName; } }
I forgot to add this case yes. But then the whole style have to be changed. So it depends also on the choosen style. I just thought about another alternative: have the members in another internal type that represent the readable properties. Not sure if it would be overkill...
|
|
|
|
|
Logged
|
|
|
|
|
Graham.
|
 |
« Reply #46 on: June 25, 2012, 09:27:23 PM » |
|
Also, get_ suggest an action while here I'm using it as a property. We can arg about that a lot and even suggest to have a property system in the language to fix this. The problem is that it looks like a matter of taste, and I can't find a strong argument for it.
mm. name() is technically an action on a property. I read a Google code convention doc once. They "strongly enforce" function names be verbs. The real argument is over the general case. Property access is one of those areas that doesn't really matter that much.... Do whatever you want. I just thought about another alternative: have the members in another internal type that represent the readable properties. Not sure if it would be overkill...
That's basically the same thing though. You'd get m.property instead of m_property.
|
|
|
|
|
Logged
|
|
|
|
|
Klaim
|
 |
« Reply #47 on: June 25, 2012, 09:52:09 PM » |
|
mm. name() is technically an action on a property. I read a Google code convention doc once. They "strongly enforce" function names be verbs. That's why I wrote "rename( new_name )" instead of "name( new_name )". I just thought about another alternative: have the members in another internal type that represent the readable properties. Not sure if it would be overkill...
That's basically the same thing though. You'd get m.property instead of m_property. I was thinking about something more semantically correct, like this: class Foo // this is stored in a map, index being the name. It also needs to keep it inside for user's use. { public: Foo( std::string name ) : properties{ name } {} // this is the "not so good" part of the idea...but made ok by C++11
const std::string& name() const { return properties.name; } // OK
// that's OK and very clear void rename( std::string new_name ) { properties.name = new_name; /*some other work to do in this case*/ }
Parent* parent() const { return parent; } // NOT OK see at the bottom
private: struct Properties { std::string name; // OK Location location; // still OK for this kind of value } properties;
SomeComplexType machine; // it's not a value-semantic property of the object, not exposed either
Parent* parent; // what about this case? it don't feel OK to put it in properties because it's not really a value... not sure about this
}; Still not perfect though, but more independent from the style. A bit overkill? It looks like having an internal namespace. The constructor would be awkward to write but with C++11 it's really easy. Too bad my compiler still don't have this feature in.
|
|
|
|
|
Logged
|
|
|
|
|
Graham.
|
 |
« Reply #48 on: June 25, 2012, 10:15:14 PM » |
|
Yeah, overkill.
Only if the contents of that struct needed to be logically united would I do that, but that's what the class is doing already. Doing so is similar to putting a present in a box in a box. You'd only do that if the inner box provides some unique function, like padding, or if you had to take it out and share it.
I've been down that thought path too.... It's like, "yes! More structure will solve this." Then you do it, and it's like, "oh, wait...."
rename() vs. name(). Same argument why get_name() is better than name(). name() is really just a short-hand for get_name(). You see name() and you know you mean you're getting a name. "name" is a noun. Variables take nouns because they exist; they don't do. So when you have name() you're entering noun space, variable territory, from the verb space that is function territory.
In a clean world, function names should always be verbs. Short-hands are hacks. But hacks are sometimes okay because they save time. A hack is basically, "this is bad in the general case, but in the interest of time, and relying on my experience, I'm going to do it anyway." Every programmer should hack sometimes, because your own time is something you want to optimize too. You can't ignore that.
If the only thing that unites things in a struct is that they all belong within the same class, then you don't need the struct.
Sometimes you want to plug functionality into data dynamically. So you have some package (struct) that you wrap in a function depending on what operations you'd like to perform on it. So you'd be like, new Person( person_like_data_struct ), constructing with a struct. Then you can access a name with person.data.name.
But in that case you're allowing access to by-pass your accessor, get_name(), because the caller is going through the struct.
So ditch the struct if its only to solve this naming problem alone. I'd do get_name(). But m_name just to give yourself the function short-hand is fine. Without bringing in macros and/or editor extensions it's impossible to silver-bullet this problem in modern languages. Either you prioritize the consistency of internal structure, or the ease of presentation.
High-level or low? The choice is a legitimate one.
|
|
|
|
|
Logged
|
|
|
|
|
Twitch
|
 |
« Reply #49 on: June 25, 2012, 10:34:06 PM » |
|
Take whichever option involves the least complexity, and suits your taste. Less is more.
get_name and set_name get my votes; it's totally obvious what they do.
|
|
|
|
|
Logged
|
|
|
|
|
VortexCortex
|
 |
« Reply #50 on: June 25, 2012, 11:49:36 PM » |
|
My code editor colors members differently than locals & globals, etc. I don't really like adding additional semantics to the core language with prefixes or suffixes. One long lived project I worked on had a local double precision float named: gi_gameTimer... It was a global integer at one point, and due to the retarding "don't thrash the CVS with needless renames" rule of the project leader it was pretty confusing. (names changed to protect the innocent).
Now, had it been named gameTimer in a proper namespace (it was C++), then changing its type in a few spots would have been simple. The same goes for member vars that get made into class wide variables and whatnot. Needless '_' semantics yield needless renaming issues.
I can rest my cursor on a name and pop up the origin, type, declaration comments, class hierarchy, scope & dependency graphs, etc. I try to work smarter not harder, so should my editor; I don't need the extra _ or whatnot to make sure I know what var does what at a glance. Really, if that's an issue, I shouldn't be editing that code if I don't grasp side effects -- That's how the most insidious bugs are born.
That said: Refactoring is made easy with tools that understand the language, so it's not that big of a deal. People can do things however they like, doesn't matter much to me, I adopt whatever coding style the project needs; Just stating my preference which has changed over the years with experience...
One exception: I code frequently in C99, which has no namespaces, so I prefix all public facing or global names (the API) with something like vc_ (changed depending on the project name) to help prevent naming collisions (manual namespaces).
|
|
|
|
|
Logged
|
|
|
|
|
Evan Balster
|
 |
« Reply #51 on: June 27, 2012, 11:49:31 AM » |
|
Average:
My argument, again, is that you can't declare a macro such as "_id" in the global namespace (where underscore-lowercase IDs are reserved) because a macro doesn't have a concept of namespace. To do so would remove the distinction in safety between _A and _a style identifiers entirely and render pointless their differing treatment in the C++ spec.
You may well have a point about that 1% chance, since this is the sort of thing that could easily be misinterpreted in the design of a standard library for some obscure OS. But I feel as though the (very very small) chance of a very nasty bug hunt during portwork balances out with the readability and simplicity this practice confers.
That said, perhaps postfixed underscores would be better.
|
|
|
|
|
Logged
|
|
|
|
|
Average Software
|
 |
« Reply #52 on: June 27, 2012, 06:49:13 PM » |
|
Average:
My argument, again, is that you can't declare a macro such as "_id" in the global namespace (where underscore-lowercase IDs are reserved) because a macro doesn't have a concept of namespace. Your logic is flawed. A macro is a name, and all macros exist the global namespace. The fact that macros don't obey scoping is irrelevant, that's a semantic concern, not a declaration concern. Macros do have a concept of namespace. C++ 16.3-7 states that all macro names occupy a single namespace. Since macros can be referenced at any scope without qualified lookup, this is by definition the global namespace.
|
|
|
|
|
Logged
|
|
|
|
|
Evan Balster
|
 |
« Reply #53 on: June 27, 2012, 07:05:46 PM » |
|
Damned spec writers. I'll never get closure on this.  At this point it seems like the best way of resolving the underscore-prefix thing would be to look for anecdotes of people getting burned, as I mentioned before. Do you know of any personally?
|
|
|
|
|
Logged
|
|
|
|
|
Average Software
|
 |
« Reply #54 on: June 28, 2012, 04:57:53 AM » |
|
Damned spec writers. I'll never get closure on this.  At this point it seems like the best way of resolving the underscore-prefix thing would be to look for anecdotes of people getting burned, as I mentioned before. Do you know of any personally? Personally no, but I can think of cases that don't even involve macros where you could get burned. Take these two related examples: namespace { int _reserved1; }
namespace MyStuff { int _reserved2; }
using namespace MyStuff;
int main() { cout << _reserved1 << endl; cout << _reserved2 << endl; } If either _reserved1 or _reserved2 happen to be used by the compiler, this code will not compile. The second case can be resolved by qualifying the name as MyStuff::_reserved2, the first case has no resolution because there's no way to explicitly specify the anonymous namespace. The end is result is code that will compile on some compilers, but not others, depending on which reserved global names are used. So even at non-global scopes, globally reserved names can cause issues. Since all names beginning with an underscore are reserved in some fashion, it's best to just stay the hell away from them. Let the compiler have its namespace, there are plenty of other names you can use.
|
|
|
|
|
Logged
|
|
|
|
|