Why use prefixes on member variables in C++ classes

前端 未结 29 1201
半阙折子戏
半阙折子戏 2020-11-28 17:39

A lot of C++ code uses syntactical conventions for marking up member variables. Common examples include

  • m_memberName for public members (where public
相关标签:
29条回答
  • 2020-11-28 17:46

    IMO, this is personal. I'm not putting any prefixes at all. Anyway, if code is meaned to be public, I think it should better has some prefixes, so it can be more readable.

    Often large companies are using it's own so called 'developer rules'.
    Btw, the funniest yet smartest i saw was DRY KISS (Dont Repeat Yourself. Keep It Simple, Stupid). :-)

    0 讨论(0)
  • 2020-11-28 17:46

    The original idea for prefixes on C++ member variables was to store additional type information that the compiler didn't know about. So for example, you could have a string that's a fixed length of chars, and another that's variable and terminated by a '\0'. To the compiler they're both char *, but if you try to copy from one to the other you get in huge trouble. So, off the top of my head,

    char *aszFred = "Hi I'm a null-terminated string";
    char *arrWilma = {'O', 'o', 'p', 's'};

    where "asz" means this variable is "ascii string (zero-terminated) and "arr" means this variable is a character array.

    Then the magic happens. The compiler will be perfectly happy with this statement:

    strcpy(arrWilma, aszFred);

    But you, as a human, can look at it and say "hey, those variables aren't really the same type, I can't do that".

    Unfortunately a lot places use standards such as "m_" for member variables, "i" for integers no matter how used, "cp" for char pointers. In other words they're duplicating what the compiler knows, and making the code hard to read at the same time. I believe this pernicious practice should be outlawed by statute and subject to harsh penalties.

    Finally, there's two points I should mention:

    • Judicious use of C++ features allows the compiler to know the information you had to encode in raw C-style variables. You can make classes that will only allow valid operations. This should be done as much as practical.
    • If your code blocks are so long that you forget what type a variable is before you use it, they are way too long. Don't use names, re-organize.
    0 讨论(0)
  • 2020-11-28 17:47

    According to JOINT STRIKE FIGHTER AIR VEHICLE C++ CODING STANDARDS (december 2005):

    AV Rule 67

    Public and protected data should only be used in structs—not classes. Rationale: A class is able to maintain its invariant by controlling access to its data. However, a class cannot control access to its members if those members non-private. Hence all data in a class should be private.

    Thus, the "m" prefix becomes unuseful as all data should be private.

    But it is a good habit to use the p prefix before a pointer as it is a dangerous variable.

    0 讨论(0)
  • 2020-11-28 17:48

    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 then m_. You also still run into naming conflicts between variables and functions when you have a int foo; and a int foo();.

    • foo = foo_; or foo = 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. Using m_ is also more extendable, as you can use g_ for globals and s_ 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..

    0 讨论(0)
  • 2020-11-28 17:49

    When you have a big method or code blocks, it's convenient to know immediately if you use a local variable or a member. it's to avoid errors and for better clearness !

    0 讨论(0)
  • 2020-11-28 17:50

    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?

    0 讨论(0)
提交回复
热议问题