Why use prefixes on member variables in C++ classes

前端 未结 29 1202
半阙折子戏
半阙折子戏 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:51

    I almost never use prefixes in front of my variable names. If you're using a decent enough IDE you should be able to refactor and find references easily. I use very clear names and am not afraid of having long variable names. I've never had trouble with scope either with this philosophy.

    The only time I use a prefix would be on the signature line. I'll prefix parameters to a method with _ so I can program defensively around them.

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

    Our project has always used "its" as a prefix for member data, and "the" as a prefix for parameters, with no prefix for locals. It's a little cutesy, but it was adopted by the early developers of our system because they saw it used as a convention by some commercial source libraries we were using at the time (either XVT or RogueWave - maybe both). So you'd get something like this:

    void
    MyClass::SetName(const RWCString &theName)
    {
       itsName = theName;
    }
    

    The big reason I see for scoping prefixes (and no others - I hate Hungarian notation) is that it prevents you from getting into trouble by writing code where you think you're referring to one variable, but you're really referring to another variable with the same name defined in the local scope. It also avoids the problem of coming up with a variable names to represent that same concept, but with different scopes, like the example above. In that case, you would have to come up with some prefix or different name for the parameter "theName" anyway - why not make a consistent rule that applies everywhere.

    Just using this-> isn't really good enough - we're not as interested in reducing ambiguity as we are in reducing coding errors, and masking names with locally scoped identifiers can be a pain. Granted, some compilers may have the option to raise warnings for cases where you've masked the name in a larger scope, but those warnings may become a nuisance if you're working with a large set of third party libraries that happen to have chosen names for unused variables that occasionally collide with your own.

    As for the its/the itself - I honestly find it easier to type than underscores (as a touch typist, I avoid underscores whenever possible - too much stretching off the home rows), and I find it more readable than a mysterious underscore.

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

    When reading through a member function, knowing who "owns" each variable is absolutely essential to understanding the meaning of the variable. In a function like this:

    void Foo::bar( int apples )
    {
        int bananas = apples + grapes;
        melons = grapes * bananas;
        spuds += melons;
    }
    

    ...it's easy enough to see where apples and bananas are coming from, but what about grapes, melons, and spuds? Should we look in the global namespace? In the class declaration? Is the variable a member of this object or a member of this object's class? Without knowing the answer to these questions, you can't understand the code. And in a longer function, even the declarations of local variables like apples and bananas can get lost in the shuffle.

    Prepending a consistent label for globals, member variables, and static member variables (perhaps g_, m_, and s_ respectively) instantly clarifies the situation.

    void Foo::bar( int apples )
    {
        int bananas = apples + g_grapes;
        m_melons = g_grapes * bananas;
        s_spuds += m_melons;
    }
    

    These may take some getting used to at first—but then, what in programming doesn't? There was a day when even { and } looked weird to you. And once you get used to them, they help you understand the code much more quickly.

    (Using "this->" in place of m_ makes sense, but is even more long-winded and visually disruptive. I don't see it as a good alternative for marking up all uses of member variables.)

    A possible objection to the above argument would be to extend the argument to types. It might also be true that knowing the type of a variable "is absolutely essential to understanding the meaning of the variable." If that is so, why not add a prefix to each variable name that identifies its type? With that logic, you end up with Hungarian notation. But many people find Hungarian notation laborious, ugly, and unhelpful.

    void Foo::bar( int iApples )
    {
        int iBananas = iApples + g_fGrapes;
        m_fMelons = g_fGrapes * iBananas;
        s_dSpuds += m_fMelons;
    }
    

    Hungarian does tell us something new about the code. We now understand that there are several implicit casts in the Foo::bar() function. The problem with the code now is that the value of the information added by Hungarian prefixes is small relative to the visual cost. The C++ type system includes many features to help types either work well together or to raise a compiler warning or error. The compiler helps us deal with types—we don't need notation to do so. We can infer easily enough that the variables in Foo::bar() are probably numeric, and if that's all we know, that's good enough for gaining a general understanding of the function. Therefore the value of knowing the precise type of each variable is relatively low. Yet the ugliness of a variable like "s_dSpuds" (or even just "dSpuds") is great. So, a cost-benefit analysis rejects Hungarian notation, whereas the benefit of g_, s_, and m_ overwhelms the cost in the eyes of many programmers.

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

    Others try to enforce using this->member whenever a member variable is used

    That is usually because there is no prefix. The compiler needs enough information to resolve the variable in question, be it a unique name because of the prefix, or via the this keyword.

    So, yes, I think prefixes are still useful. I, for one, would prefer to type '_' to access a member rather than 'this->'.

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

    I use m_ for member variables just to take advantage of Intellisense and related IDE-functionality. When I'm coding the implementation of a class I can type m_ and see the combobox with all m_ members grouped together.

    But I could live without m_ 's without problem, of course. It's just my style of work.

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

    I think that, if you need prefixes to distinguish class members from member function parameters and local variables, either the function is too big or the variables are badly named. If it doesn't fit on the screen so you can easily see what is what, refactor.

    Given that they often are declared far from where they are used, I find that naming conventions for global constants (and global variables, although IMO there's rarely ever a need to use those) make sense. But otherwise, I don't see much need.

    That said, I used to put an underscore at the end of all private class members. Since all my data is private, this implies members have a trailing underscore. I usually don't do this anymore in new code bases, but since, as a programmer, you mostly work with old code, I still do this a lot. I'm not sure whether my tolerance for this habit comes from the fact that I used to do this always and am still doing it regularly or whether it really makes more sense than the marking of member variables.

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