Why use prefixes on member variables in C++ classes
Solution 1
You have to be careful with using a leading underscore. A leading underscore before a capital letter in a word is reserved. For example:
_Foo
_L
are all reserved words while
_foo
_l
are not. There are other situations where leading underscores before lowercase letters are not allowed. In my specific case, I found the _L happened to be reserved by Visual C++ 2005 and the clash created some unexpected results.
I am on the fence about how useful it is to mark up local variables.
Here is a link about which identifiers are reserved: What are the rules about using an underscore in a C++ identifier?
Solution 2
I'm all in favour of prefixes done well.
I think (System) Hungarian notation is responsible for most of the "bad rap" that prefixes get.
This notation is largely pointless in strongly typed languages e.g. in C++ "lpsz" to tell you that your string is a long pointer to a nul terminated string, when: segmented architecture is ancient history, C++ strings are by common convention pointers to nul-terminated char arrays, and it's not really all that difficult to know that "customerName" is a string!
However, I do use prefixes to specify the usage of a variable (essentially "Apps Hungarian", although I prefer to avoid the term Hungarian due to it having a bad and unfair association with System Hungarian), and this is a very handy timesaving and bug-reducing approach.
I use:
- m for members
- c for constants/readonlys
- p for pointer (and pp for pointer to pointer)
- v for volatile
- s for static
- i for indexes and iterators
- e for events
Where I wish to make the type clear, I use standard suffixes (e.g. List, ComboBox, etc).
This makes the programmer aware of the usage of the variable whenever they see/use it. Arguably the most important case is "p" for pointer (because the usage changes from var. to var-> and you have to be much more careful with pointers - NULLs, pointer arithmetic, etc), but all the others are very handy.
For example, you can use the same variable name in multiple ways in a single function: (here a C++ example, but it applies equally to many languages)
MyClass::MyClass(int numItems)
{
mNumItems = numItems;
for (int iItem = 0; iItem < mNumItems; iItem++)
{
Item *pItem = new Item();
itemList[iItem] = pItem;
}
}
You can see here:
- No confusion between member and parameter
- No confusion between index/iterator and items
- Use of a set of clearly related variables (item list, pointer, and index) that avoid the many pitfalls of generic (vague) names like "count", "index".
- Prefixes reduce typing (shorter, and work better with auto-completion) than alternatives like "itemIndex" and "itemPtr"
Another great point of "iName" iterators is that I never index an array with the wrong index, and if I copy a loop inside another loop I don't have to refactor one of the loop index variables.
Compare this unrealistically simple example:
for (int i = 0; i < 100; i++)
for (int j = 0; j < 5; j++)
list[i].score += other[j].score;
(which is hard to read and often leads to use of "i" where "j" was intended)
with:
for (int iCompany = 0; iCompany < numCompanies; iCompany++)
for (int iUser = 0; iUser < numUsers; iUser++)
companyList[iCompany].score += userList[iUser].score;
(which is much more readable, and removes all confusion over indexing. With auto-complete in modern IDEs, this is also quick and easy to type)
The next benefit is that code snippets don't require any context to be understood. I can copy two lines of code into an email or a document, and anyone reading that snippet can tell the difference between all the members, constants, pointers, indexes, etc. I don't have to add "oh, and be careful because 'data' is a pointer to a pointer", because it's called 'ppData'.
And for the same reason, I don't have to move my eyes out of a line of code in order to understand it. I don't have to search through the code to find if 'data' is a local, parameter, member, or constant. I don't have to move my hand to the mouse so I can hover the pointer over 'data' and then wait for a tooltip (that sometimes never appears) to pop up. So programmers can read and understand the code significantly faster, because they don't waste time searching up and down or waiting.
(If you don't think you waste time searching up and down to work stuff out, find some code you wrote a year ago and haven't looked at since. Open the file and jump about half way down without reading it. See how far you can read from this point before you don't know if something is a member, parameter or local. Now jump to another random location... This is what we all do all day long when we are single stepping through someone else's code or trying to understand how to call their function)
The 'm' prefix also avoids the (IMHO) ugly and wordy "this->" notation, and the inconsistency that it guarantees (even if you are careful you'll usually end up with a mixture of 'this->data' and 'data' in the same class, because nothing enforces a consistent spelling of the name).
'this' notation is intended to resolve ambiguity - but why would anyone deliberately write code that can be ambiguous? Ambiguity will lead to a bug sooner or later. And in some languages 'this' can't be used for static members, so you have to introduce 'special cases' in your coding style. I prefer to have a single simple coding rule that applies everywhere - explicit, unambiguous and consistent.
The last major benefit is with Intellisense and auto-completion. Try using Intellisense on a Windows Form to find an event - you have to scroll through hundreds of mysterious base class methods that you will never need to call to find the events. But if every event had an "e" prefix, they would automatically be listed in a group under "e". Thus, prefixing works to group the members, consts, events, etc in the intellisense list, making it much quicker and easier to find the names you want. (Usually, a method might have around 20-50 values (locals, params, members, consts, events) that are accessible in its scope. But after typing the prefix (I want to use an index now, so I type 'i...'), I am presented with only 2-5 auto-complete options. The 'extra typing' people attribute to prefixes and meaningful names drastically reduces the search space and measurably accelerates development speed)
I'm a lazy programmer, and the above convention saves me a lot of work. I can code faster and I make far fewer mistakes because I know how every variable should be used.
Arguments against
So, what are the cons? Typical arguments against prefixes are:
"Prefix schemes are bad/evil". I agree that "m_lpsz" and its ilk are poorly thought out and wholly useless. That's why I'd advise using a well designed notation designed to support your requirements, rather than copying something that is inappropriate for your context. (Use the right tool for the job).
"If I change the usage of something I have to rename it". Yes, of course you do, that's what refactoring is all about, and why IDEs have refactoring tools to do this job quickly and painlessly. Even without prefixes, changing the usage of a variable almost certainly means its name ought to be changed.
"Prefixes just confuse me". As does every tool until you learn how to use it. Once your brain has become used to the naming patterns, it will filter the information out automatically and you won't really mind that the prefixes are there any more. But you have to use a scheme like this solidly for a week or two before you'll really become "fluent". And that's when a lot of people look at old code and start to wonder how they ever managed without a good prefix scheme.
"I can just look at the code to work this stuff out". Yes, but you don't need to waste time looking elsewhere in the code or remembering every little detail of it when the answer is right on the spot your eye is already focussed on.
(Some of) that information can be found by just waiting for a tooltip to pop up on my variable. Yes. Where supported, for some types of prefix, when your code compiles cleanly, after a wait, you can read through a description and find the information the prefix would have conveyed instantly. I feel that the prefix is a simpler, more reliable and more efficient approach.
"It's more typing". Really? One whole character more? Or is it - with IDE auto-completion tools, it will often reduce typing, because each prefix character narrows the search space significantly. Press "e" and the three events in your class pop up in intellisense. Press "c" and the five constants are listed.
"I can use
this->
instead ofm
". Well, yes, you can. But that's just a much uglier and more verbose prefix! Only it carries a far greater risk (especially in teams) because to the compiler it is optional, and therefore its usage is frequently inconsistent.m
on the other hand is brief, clear, explicit and not optional, so it's much harder to make mistakes using it.
Solution 3
I generally don't use a prefix for member variables.
I used to use a m
prefix, until someone pointed out that "C++ already has a standard prefix for member access: this->
.
So that's what I use now. That is, when there is ambiguity, I add the this->
prefix, but usually, no ambiguity exists, and I can just refer directly to the variable name.
To me, that's the best of both worlds. I have a prefix I can use when I need it, and I'm free to leave it out whenever possible.
Of course, the obvious counter to this is "yes, but then you can't see at a glance whether a variable is a class member or not".
To which I say "so what? If you need to know that, your class probably has too much state. Or the function is too big and complicated".
In practice, I've found that this works extremely well. As an added bonus it allows me to promote a local variable to a class member (or the other way around) easily, without having to rename it.
And best of all, it is consistent! I don't have to do anything special or remember any conventions to maintain consistency.
By the way, you shouldn't use leading underscores for your class members. You get uncomfortably close to names that are reserved by the implementation.
The standard reserves all names starting with double underscore or underscore followed by capital letter. It also reserves all names starting with a single underscore in the global namespace.
So a class member with a leading underscore followed by a lower-case letter is legal, but sooner or late you're going to do the same to an identifier starting with upper-case, or otherwise break one of the above rules.
So it's easier to just avoid leading underscores. Use a postfix underscore, or a m_
or just m
prefix if you want to encode scope in the variable name.
Solution 4
I prefer postfix underscores, like such:
class Foo
{
private:
int bar_;
public:
int bar() { return bar_; }
};
Solution 5
Lately I have been tending to prefer m_ prefix instead of having no prefix at all, the reasons isn't so much that its important to flag member variables, but that it avoids ambiguity, say you have code like:
void set_foo(int foo) { foo = foo; }
That of cause doesn't work, only one foo
allowed. So your options are:
this->foo = foo;
I don't like it, as it causes parameter shadowing, you no longer can use
g++ -Wshadow
warnings, its also longer to type thenm_
. You also still run into naming conflicts between variables and functions when you have aint foo;
and aint foo();
.foo = foo_;
orfoo = arg_foo;
Been using that for a while, but it makes the argument lists ugly, documentation shouldn't have do deal with name disambiguity in the implementation. Naming conflicts between variables and functions also exist here.
m_foo = foo;
API Documentation stays clean, you don't get ambiguity between member functions and variables and its shorter to type then
this->
. Only disadvantage is that it makes POD structures ugly, but as POD structures don't suffer from the name ambiguity in the first place, one doesn't need to use it with them. Having a unique prefix also makes a few search&replace operations easier.foo_ = foo;
Most of the advantages of
m_
apply, but I reject it for aesthetic reasons, a trailing or leading underscore just makes the variable look incomplete and unbalanced.m_
just looks better. Usingm_
is also more extendable, as you can useg_
for globals ands_
for statics.
PS: The reason why you don't see m_
in Python or Ruby is because both languages enforce the their own prefix, Ruby uses @
for member variables and Python requires self.
.
Related videos on Youtube
VoidPointer
Updated on April 27, 2022Comments
-
VoidPointer about 2 years
A lot of C++ code uses syntactical conventions for marking up member variables. Common examples include
- m_memberName for public members (where public members are used at all)
- _memberName for private members or all members
Others try to enforce using this->member whenever a member variable is used.
In my experience, most larger code bases fail at applying such rules consistently.
In other languages, these conventions are far less widespread. I see it only occasionally in Java or C# code. I think I have never seen it in Ruby or Python code. Thus, there seems to be a trend with more modern languages to not use special markup for member variables.
Is this convention still useful today in C++ or is it just an anachronism. Especially as it is used so inconsistently across libraries. Haven't the other languages shown that one can do without member prefixes?
-
Joe almost 15 yearsI prefer it; in complex codebases it can be important to know which vars are local and which aren't. I generally use the prefix over forcing this-> which I find to be a lot of extra typing and optional (whereas naming will force you to do it)
-
Steve Jessop almost 15 yearsYou've never seen it in Ruby because of @ for attribute, and the idiom of generating accessors in preference to using attributes directly.
-
Nathan Osman about 11 yearsAccording to PEP 8 non-public member variables are to be prefixed with an underscore in Python (example:
self._something = 1
). -
too almost 9 yearsShouldn't editor's syntax highlighting be used to identify these?
-
matec about 8 yearsYou do have seen the equivalent of
this->member
in Python code. In Python it would typically beself.member
and it is not only a convention, it is required by the language. -
Kostiantyn Ponomarenko almost 6 yearsThis may be interesting for you: github.com/isocpp/CppCoreGuidelines/blob/master/…
-
mosegui over 2 yearsThe use of
this->memberVar
is not just a matter of style. The C++ standard establishes that non-dependent members are not searched for in dependent classes. That means that if you are in a child class trying to access a member variable defined in a parent class template, you will have to either provide a qualified name for that variableBaseClass<FooBar>::memberVar
or, if the variable type might depend on the specific instantiation, you might end up with no choice but to access it over the specific class instancethis->memberVar
. See e.g. stackoverflow.com/a/24368629/4276112
-
Admin almost 15 yearsActually, both _foo and _l are reserved at namespace scope.
-
rmeador almost 15 yearsthe compiler can resolve it anyways... local variables will hide ones in higher scope in most langauges. It's for the (dubious) benefit of the humans reading the code. Any decent IDE will highlight locals/members/globals in different ways so there's no need for this sort of stuff
-
Juan almost 15 yearsBut they are ok as member variable names. I don't prefix underscores, because the rules are too confusing, and I had gotten burned in the past.
-
aroon65 almost 15 yearsExactly. Locals will hide class members. Consider a constructor that sets these members. Usually it makes sense to name the parameters the same as the members.
-
Martin Beckett almost 15 yearsThe problem with using m, rather than m_ (or _) is with the current fashion for camel case it makes it difficult to read some variable names.
-
Admin almost 15 yearsI have a cunning plan for dealing with that - I don't use camel case.
-
sbi almost 15 yearsIf you have a big method, for better clearness break it down.
-
VoidPointer almost 15 yearsThis very much reflects my on feeling about this issue. Code should be readable without resorting to prefixes. Maybe we don't see so much prefix uses in more modern languages because their user communities have embraced readability a bit more than what you sometimes see in C++. Of course, C++ can and should be readable. It's just that a lot of unreadable C++ has been written over the years.
-
josesuero almost 15 yearshow so? The destructor doesn't have access to local variables declared in other functions, so there's no room for confusion there. Besides, heap-allocated local variables shouldn't exist. And heap-allocated member variables should only exist inside RAII classes, pretty much.
-
Ed S. almost 15 yearsExactly why I use 'm_'. I don't like locals with the same name as my member vars.
-
josesuero almost 15 yearsI just don't create locals with the same names as member vars in the first place. If they exist, it's a pretty good hint that your code needs to be refactored.
-
Steve Broberg almost 15 yearsThere are lots of reasons not to break down some big methods. For example, if your method needs to keep a lot of local state, you either have to pass lots of parameters into your subordinate methods, create new classes that exist solely for the purpose of passing data between these methods, or declaring the state data as member data of the parent class. All of these have problems that would affect the clarity or maintainability of the method, compared to a single long-ish method (especially one whose logic is straightforward).
-
Admin almost 15 years@jalf and I should have said multi word class/function names like this: DepositBankAccount.
-
aroon65 almost 15 yearsWhy is that a code smell? I'd say it's perfectly common and reasonable, especially when it comes to constructors.
-
Ed S. almost 15 years@jalf: That is not true at all. How about a class that has a "Name" property? In the constructor, I want that info, so I take a parameter called... "name"! Oh wait, my member variable that backs "Name" is called "name". Why does that need refactoring?
-
Pavel Minaev almost 15 yearsA constructor should (generally) set locals in its initialization list. And there, parameters don't shadow field names, but both are accessible - so you can write
struct Foo { int x; Foo(int x) : x(x) { ... } };
-
Steve Jessop almost 15 yearsI assume the problem with that comes when you do
Foo(int x, bool blee) : x(x) { if (blee) x += bleecount; } // oops, forgot this->
I prefer to call my member variables something useful and then give constructor parameters that match them abbreviated names:Foo(int f) : foo(f) {...}
-
Admin almost 15 yearsNot unless he explains why the underscore. I'm a big fan of his "Rapid Development" book, which I've recommended here numerous times, but much less of "Code Complete" (which I will admit I haven't read since it first came out).
-
Rob almost 15 yearsMe too. I also give accessors/mutators the same name.
-
mmmmmmmm almost 15 years@neil: What is "DepositBankAccount" if it isn't camel case?
-
mmmmmmmm almost 15 years@Pavel: Constructors should do so, but they can't always. For example it could be that there is no copy constructor in the type you use and you have to copy by hand inside your constructor body.
-
Admin almost 15 yearsI thoght camel case was "depositBankAccount". Or am I getting confused?
-
frankster almost 15 years"heap-allocated local variables shouldn't exist" is a bit strong. But if/when you use them, its super-important to make sure that they get deallocated corectly, so a disciplined naming convention for member versus local variables assists immeasurably with ensuring this.
-
josesuero almost 15 yearsAh, I see. As far as I know, depositBankAccount is camel-case, and I think the most common name for DepositBankAccount is Pascal-case? (I never used Pascal, but I've heard this described as Pascal-case fairly often.)
-
Admin almost 15 years@jalf I first learned Pascal in 1980, and back then people used a mishmash of ways of naming things. Borland's Delphi (probably the only Pascal survivor) uses the DepositBankAccount style, but so does what must be the most influential tech of them all - the Windows API.
-
mmmmmmmm almost 15 years@neil: I don't know exactly and simply thought both "depositBankAccount" and "DepositBankAccount" were camel case. Let's take a look what wikipedia says... Hey! They say the same! But is Wikipedia a authoritative source for this?
-
VoidPointer almost 15 yearsI mean to have read that the problem with Hungarien Notation just resulted from Simonyi being misunderstood. He wrote a prefix should be used to indicate the type of a variable where he meant "type" like in "kind of thing" not literal datatype. Later the platform guys at Microsoft picked it up and came up with lpsz... and the rest is history...
-
VoidPointer almost 15 yearsPrefixes that indicate type or kind of variable are also something worth a discussion, but I was referring mainly to prefixes indicating whether something is a (private) member/field. The reverse Hungarian notation you are mentioning can be quite handy when applied intelligently (like in your example). My favorite example where it makes sense is relative and absolute coordinates. when you see absX = relX you can plainly see that something might be wrong.you can also name functions accordingly: absX = absFromRel(relX, offset);
-
jkeys almost 15 yearsPlease don't be making your member variables public. Just use accessors. The parentheses should tell the reader that it is a member variable.
-
mmmmmmmm almost 15 years@neil: I think there are far more naming conventions then there are names for. (I'm sure there are even people combining underscores with capital letters (Deposit_Bank_Account) and I'm sure there is no name for that :-)
-
Niels Dekker almost 15 yearsNote: the initialization of aszFred is questionable (offering non-const access to a literal string), and the initialization of arrWilma won't even compile. (You probably intended to declare arrWilma as an array, instead of a pointer!) No problem though, as you wrote that it's just off the top of your head... :-)
-
ya23 over 14 yearsInteresting. Looks a bit ugly at first, but I can see how it can be beneficial.
-
A. L. Flanagan over 14 yearsOops, you're absolutely right. Kids, don't try that at home. Do this: 'const char *aszFred = "Hi I'm a null-terminated string"; char arrWilma[] = {'O', 'o', 'p', 's'};'
-
Dan over 14 years@rstevens: I thought This_Was_Called_Ada (Ada code is the only place I've seen that convention)
-
TonyK over 13 yearsThese are not reserved words. They are reserved names. If they were reserved words, you couldn't use them at all. Because they are reserved names, you can use them, but at your own risk.
-
josesuero almost 13 years"s is for static" sounds pretty much like the "bad" form of Hungarian to me.
-
mbarnett almost 13 years"So a class member with a leading underscore followed by a lower-case letter is legal, but sooner or late you're going to do the same to an identifier starting with upper-case, or otherwise break one of the above rules." -- class member variables aren't in the global namespace, so a leading underscore is safe, regardless of whether it's followed by a lower or uppercase letter.
-
josesuero almost 13 years@mbarnett: No, underscore followed by upper-case is reserved in general, not just in the global namespace.
-
Platinum Azure over 12 years@MartinBeckett: You should capitalize the
a
in that scenario-- you're not doing it right otherwise.mApData
(m
prefix, then the variable name isapData
). -
Jason Williams over 12 yearsThen don't use it... Unless you think that your usage of the variable might be influenced by knowing that it is static...
-
user541686 about 12 yearsThe
lps
might be redundant, but thez
isn't. It's certainly good to know whether a string is zero-terminated or not. -
Jason Williams about 12 years@Mehrdad: I don't think
z
is very often useful in a language like C++ where that sort of low level implementation detail should be encapsulated in a class, but in C (where zero-termination is an important distinction) I agree with you. IMO any scheme we use should be adapted as required to best suit our own needs - So, if zero-termination affects your usage of the variable, there's nothing wrong with declaring "z" a useful prefix. -
Thomas Eding over 11 years
The most important case is "p" for pointer (because the usage changes from var. to var-> and you have to be much more careful with pointers.
I whole heartedly disagree. If I use a pointer wrong, it simply won't compile (void*
may be an exception for double pointers though). And the whole->
over.
is enough to tell me it is a pointer. Also, if you are using autocomplete, your editor probably has declaration tooltips, eliminating the need for prefixing for variable information. Regardless, good answer. -
Jason Williams over 11 years@Thomas: All good points. Some benefits are strong, some weaker. The stronger cases for p are for multiple indirections (X vs pX vs ppX) and pointer arithmetic (X++ vs pX++ vs *pX++), where knowing that something is a pointer is vital. For me, the other cases are still useful - compiling or tooltipping are IMO just less efficient ways of determining that a variable is a pointer (and the other cons: tooltips can't be copied and pasted into examples outside of your IDE, etc).
-
Admin almost 11 yearsUpvoted for the clear, comprehensive and interesting explanations, however there is little here suggesting how this saves time in C++ YET remains largely unused in many other languages.
-
ulidtko almost 10 yearsI'd also add
n
for 1-based numbers, counts and indexes. It's proven very useful to me. To be fair, indexes ought to be all 0-based (and have prefixi
), but things happen. Then
prefix helps to catch errors with index arithmetic. For example,int iLastItem = nDataItems - 1;
should look fine to your internal typechecker, whilem_TreeIndices[nLeftChild] = (iParent >= 1) ? iRightChild : null;
should totally not. -
Marson Mao almost 10 yearssurprised that this answer's vote is less than the prefix one.
-
Korchkidu over 9 yearsOne of the nice point about auto is to not commit to some datatype. Weird that we would need to put this in the variable names now.
-
Jason Williams over 9 years@Korchkidu: auto/var can be useful where types are unknown, but most people use them to be lazy (avoid typing the big long type name) and this introduces exactly the "what type am I working with here?" problem that prefixes help to address. Hiding known types behind unnecessary autos is a very unhelpful practice as it obfuscates the code.
-
Korchkidu over 9 years@JasonWilliams: I have been refactoring code a lot those days. I wish I was using auto more. And not only for typing less. Auto forces you not to commit to some type. This is really helping in the long-run. IMHO of course. And not knowing which type your are working with is not a problem, it is a nice "feature" actually.
-
Reid Ellis over 9 yearsIn terms of naming, as soon as I see "numItems", I cringe. Variables should not be (implied) prepositional phrases ("number (of) items"). Rather, they should be nouns or noun phrases, e.g. "itemCount".
-
Jason Williams over 9 yearsThat's a point of grammar which is correct but largely irrelevant in terms of "will people reading this code understand my intent?". I think numItems/itemCount are both fine, though generally readability flows from using a natural form, while yodaSpeak reduces it. (Aside: "count" isn't just a noun, it's also a verb. Consider .Net's IEnumerable.Count - does this return the "number of items" in a collection, or does it enumerate the collection and actually "count" how many items there are? This is a very important distinction which can be the cause of some horrific performance issues)
-
sydan about 9 yearsI'd say it's a lot lot less ugly than:" mBar" or "m_bar".
-
avim about 9 yearsbut then you have
vector<int> v_;
and writingv_.push_back(5)
is pretty ugly too -
Alexandru Irimiea over 8 yearsIs it recommended to use
p
prefix for smart pointers too? E.g.:std::unique_ptr<MyObject> pMyObject;
-
Jason Williams over 8 yearsIt's up to you, but I'd say it's still a pointer so I'd use a "p" prefix for consistency... or if you feel it's important to differentiate smart pointers from regular ones, use a distinct prefix - e.b. you may prefer p for smart pointers and something like d for dangerous ones!)
-
Justme0 over 8 yearsThat's Google C++ style.
-
underscore_d over 8 yearsto be fair, you missed at least 2 other options, e.g. (a) use full names like
foo
only for members and instead use single-letter or short names for parameters or other locals/throwaways, such asint f
; or (b) prefix the parameters or other locals with something. good point rem_
and pods, though; i've independently arrived at a preference to follow both of those guidelines, for the most part. -
underscore_d over 8 years"between things such as public and private members" - how common is this really? i don't recall seeing it, but then again, i don't go around reviewing codebases or anything.
-
Mr. Will over 8 yearsI don't do it in my own coding, but I've worked at places where we had to do it based on their code convention guides. I prefer to not do it as almost all IDEs will show private variables a different color.
-
underscore_d over 8 yearsHmm, I guess it only happens in different situations than mine. Normally I use either
class
es all of whose members areprivate
/protected
, or PODstruct
s all of whose variables arepublic
(and often alsoconst
). So, I never need to wonder about the access level of any given member. -
DBedrenko about 8 yearsThanks for the answer. I'm adopting your style. When multiple prefixes apply do you include all of them, e.g.
mpsMyVar
? I'm guessing in alphabetical order? -
Jason Williams about 8 years@SpaghettiCat: Good question. For C++, yes (e.g. 'p' is a local pointer, 'mp' is a member pointer, so there is a significant difference). In C# a const or static implies that it's a member, so I just use 'm', 'c' or 's' on their own. So I adjust the scheme to best fit each language I use it in. Order them however you prefer, just try to be consistent,
-
DBedrenko about 8 yearsI was thinking that applying this convention to public members is not good, because it makes the API provided to others look less clean. Not everyone will understand the convention and it has the potential to confuse. So I'll following the Android variation where public members aren't prefixed with "m" (... I'm not sure whether I should also not apply the other prefixes...)
-
Jason Williams about 8 years@SpaghettiCat: This description is based on the assumption that classes use encapsulation, i.e. that member variables are never public. To expose a member variable to external callers, we would provide an accessor or property (to which the member variable prefixing scheme would not normally be applied).
-
Guney Ozsan about 8 yearsThis is the most intuitive solution with the fastest learning curve I've ever heard. I wish spoken languages were more flexible to handle all those so that we didn't have to think about coming up with new techniques to solve ambiguities in code.
-
Terrabits almost 8 yearsThis is the reason I prefix. I think
foo.name()
is much more readable thanfoo.get_name()
in my opinion. -
sourcedelica over 7 yearsAfter working with C++ for a little bit I can see one reason why prefixing is more popular in that language. It's because member variables and member functions share the same namespace, unlike Java and more modern languages. You run out of names faster. It's pretty annoying actually.
-
David over 7 yearsI agree with this answer, just use
this->
if you need to specify that its a member variable, or don't, that's good too. -
Caduchon over 6 yearsNote that there is a warning in gcc (>= 4.6) to detect clash of names :
-Wshadow
-
Caduchon over 6 yearsMoreover, you don't have to document your convention to give your code to other people. Everyone understand what
this->
means. -
Ruslan over 6 yearsDouble underscore is reserved in any position, not only at the beginning of the name.
-
Sascha over 6 yearsTo support this: C++ Core Guidelines don't use prefixes in their examples either: isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
-
user924 about 6 yearsfor constants it's better to use without prefix but all letters are uppercase - CONSTANT_VARIABLE
-
Jason Williams about 6 years@user924: All-caps/underscores were historically popular so you'll see them used a lot, but are no longer considered "best practice". They make code (and documentation) less readable, and many environments (C, C++, C#, VB, Java) assign special meaning to underscores. Using a prefixing scheme is more consistent and means less work when refactoring a member between being a constant, a property or variable. It also allows you to differentiate constant, readonly, & macro. You can use whatever scheme you wish: I'd just encourage you to think about the reason for preferring that scheme.
-
Toast about 5 yearsYou could also type
this->
-
Chris Olsen about 4 yearsThanks for the s_ idea. Seems very useful, and somehow had never occurred to me.
-
Oleksa almost 4 years@jalf: Why do you think "s for static" is bad?
-
antho over 3 years@Jason Williams: What do you use for a C array? mArray, pArray or something else?
-
Jason Williams over 3 years@antho: I tend to use a suffix for lists (of any form, i.e. arrays, list collections, linked lists - so an array of vehicles would be a "vehicleList"). Any prefix should clarify the usage of the array ("m" for member etc). Consider: Giving every string a "p" prefix just because it's technically a "pointer to an array of char" wouldn't typically add value (we don't usually need to "use" strings as arrays), so I usually wouldn't use a prefix, but if I were using a pointer-to-char to step through the characters within a string, I would absolutely use a "p" prefix to clarify this.
-
antho over 3 yearsOk thanks, the combination of sufix and prefix might be good. Thanks for your advice
-
Cuadrix over 3 yearsI don't like this coding style at all. Suffixes are all subjective and might refer to any type of variable depending on the coder (like you just demonstrated), while a simple use of "this->" is clear and unambiguous. Not to mention that this suffix style just brings noise to code bases that prefer the usage of "snake_case" for consistency with the standard library. That being said, I'd rather avoid suffixes.
-
Dan Bechard over 3 years@underscore_d Parameter names are part of the public interface of a class. That should be the last place you're adding weird naming conventions. Also, single letter variable names are awful and should be avoided at all costs with very few exceptions (i in a loop).
-
Traummaennlein about 2 yearsBut that's more typing ;-)