Что означает префикс переменной m_?


155

Я часто вижу m_префикс , используемый для переменных ( m_World, m_Sprites, ...) в учебные пособия, примеры и другого кода , в основном связанные с развитием игры.

Почему люди добавляют префикс m_к переменным?



18
Прежде чем бездумно следовать примеру с венгерской нотацией, сделайте небольшую проверку истории того, что на самом деле является венгерская нотация. Потому что называть int iCounter просто бессмысленно. Но разумно называть int xAnnotationPos и ​​yAnnotationPos. Используйте семантическую версию.
— АксельК

Иногда импортируемые модули префиксируют функции и переменные, так что вы с меньшей вероятностью перезапишите их своим собственным кодом. Это способ «зарезервировать» имена для конкретного использования.
— earthmeLon

3
В то время как «венгерская» нотация часто злобно высмеивается, ее особая разновидность, обозначающая переменную область действия, имеет некоторые реальные преимущества. Помимо определения области действия переменной, он предотвращает конфликты имен, например, когда у local, parm и member все одно и то же намерение и, следовательно, одно и то же «семантическое» имя. Это может сделать обслуживание больших баз кода проще и менее подверженным ошибкам.
— Hot Licks

8
Существуют аргументы за и против любого стандарта кодирования, но в вопросе четко задается вопрос, для чего m_, однако половина ответов здесь - это комментарий о том, почему все считают, что их нынешний фаворит - лучший.
— cz

Ответы:


108

Это типичная практика программирования для определения переменных, которые являются переменными-членами. Поэтому, когда вы используете их позже, вам не нужно видеть, где они определены, чтобы знать их область применения. Это также замечательно, если вы уже знаете область действия и используете что-то вроде intelliSense , вы можете начать с того, что отобразитсяm_ список всех ваших переменных-членов. Часть венгерской нотации, смотрите часть о сфере действия в примерах здесь .


51
Наихудший аргумент для соглашения об именах - вы можете просто нажать ctrl + space для intellisense.
— orlp

11
@ nightcracker, хотя мне не нравится префикс, он хочет сказать, что когда вы набираете m_, а затем «CTRL + SPACE» (если это не авто), вы получаете список, содержащий только ваших членов. Не совсем хорошая причина, но это плюс.
— Сидар

13
Стоит отметить, что существует множество других более или менее стандартных способов сделать то же самое; «m_variable», «m_Variable», «mVariable», «_variable», «_Variable» ... какой из них является «наилучшим» или «правильным» (или нужно ли вообще это делать) - такой же спорный и бесплодный аргумент, как и « пробелы против табуляции. :)
— Тревор Пауэлл

49
Я предпочитаю просто использовать "this->" - вроде как делает "m_" избыточным и даже лучше, так как это обеспечивается компилятором (теоретически вы можете вытолкнуть "m_" для любого типа переменной; это нельзя сделать с помощью "this-> «). Часть меня желает, чтобы C ++ просто стандартизировался, сделав обязательным "this->". Но это больше входит в мир обсуждения, чем в ответ.

3
@ LaurentCouvidou, вы не можете на самом деле обеспечить, чтобы разработчики создавали переменные-члены с префиксом m_.
— SomeWritesReserved

94

В Чистом коде: Справочник по мастерству гибкого программного обеспечения есть явная рекомендация против использования этого префикса:

Вам также больше не нужно добавлять префикс членских переменных m_. Ваши классы и функции должны быть достаточно маленькими, чтобы они вам не нужны.

Есть также пример (код C #) этого:

Плохая практика:

public class Part
{
    private String m_dsc; // The textual description

    void SetName(string name)
    {
        m_dsc = name;
    }
}

Хорошая практика:

public class Part
{
    private String description;

    void SetDescription(string description)
    {
        this.description = description;
    }
}

Мы рассчитываем с конструкциями языка для обозначения переменных - членов в случае явного неоднозначности ( т.е. , descriptionчленов и descriptionпараметров): this.


6
Формулировка может быть «существует явная рекомендация ПРОТИВ использования этого префикса:»
— Xofo

Я так рад, что кто-то написал это
— dmitreyg

Другая причина в том, что в java getter / setter предполагается, что getName / setName, так что getM_name плохой, и вам нужно обрабатывать их один за другим.
— Леон

Спасибо, что написали это. Я просто хотел отметить, что книга, которую вы цитировали, выходит с августа 2008 года - и я до сих пор нахожу эту плохую практику в новом коде сегодня (2019).
— alexlomba87

20

Это обычная практика в C ++. Это связано с тем, что в C ++ нельзя использовать одно и то же имя для функции-члена и переменной-члена, а функции-получатели часто называются без префикса «get».

class Person
{
   public:
      std::string name() const;

   private:
      std::string name; // This would lead to a compilation error.
      std::string m_name; // OK.
};

main.cpp:9:19: error: duplicate member 'name'
      std::string name;
                  ^
main.cpp:6:19: note: previous declaration is here
      std::string name() const;
                  ^
1 error generated.

http://coliru.stacked-crooked.com/a/f38e7dbb047687ad

«m_» означает «член». Префикс "_" также распространен.

Вы не должны использовать его в языках программирования, которые решают эту проблему, используя различные соглашения / грамматику.


11

m_Префикс часто используются для переменных - членов - Я думаю , его главное преимущество заключается в том, что она помогает создать четкое различие между общественной собственностью и частной поддержкой переменного члена документа :

int m_something

public int Something => this.m_something; 

Это может помочь иметь согласованное соглашение об именах для резервных переменных, и m_префикс является одним из способов сделать это - тот, который работает в нечувствительных к регистру языках.

Насколько это полезно, зависит от языков и инструментов, которые вы используете. Современные IDE с мощными инструментами рефакторинга и intellisense меньше нуждаются в подобных соглашениях, и это, конечно, не единственный способ сделать это, но в любом случае стоит знать об этой практике.


5
Если вам приходится писать this.на вашем языке, то m_это действительно бесполезно.
— Руслан

@Ruslan m_должен отличать его от свойства, которое он поддерживает, поэтому this.Somethingдля свойства против this.m_somethingподдерживающего члена. Это не соглашение, которое я предпочитаю сам, но я видел его в основном в нечувствительных к регистру языках (таких как VB).
— Кит

1
Почему бы не this.Somethingдля собственности и this.somethingдля поддержки? Или this._somethingдля поддержки? this.m_somethingизбыточно Я использую его _somethingтак, чтобы случайно не набирать его при Something
— вводе текста

@AustinWBryan смотрите мой предыдущий комментарий о нечувствительных к регистру языках. Да, сам по себе _префикс сделает эту работу, но m_это соглашение. Это не тот, который я бы использовал лично, но если вы видите это в коде, который был намерением автора.
— Кит

7

Как указано в других ответах, m_префикс используется для указания того, что переменная является членом класса. Это отличается от венгерской нотации, потому что она указывает не тип переменной, а ее контекст.

Я использую m_в C ++, но не в некоторых других языках, где «this» или «self» является обязательным. Мне не нравится, когда 'this->' используется с C ++, потому что он загромождает код.

Другой ответ гласит m_dsc: «плохая практика» и «описание»; это "хорошая практика", но это красная сельдь, потому что проблема в сокращении.

В другом ответе говорится, что при наборе текста thisпоявляется IntelliSense, но в любой хорошей IDE есть горячая клавиша для вызова IntelliSense для текущих учеников.


«но это красная сельдь» - хорошая мысль. Справедливое сравнение будет m_descriptionпротив description.
— Битва

3

Как указано во многих других ответах, m_ - это префикс, который обозначает переменные-члены. Он / обычно используется в мире C ++ и распространяется и на другие языки, включая Java.

В современной IDE она полностью избыточна, так как подсветка синтаксиса показывает, какие переменные являются локальными, а какие - членами . Однако к тому моменту, когда подсветка синтаксиса появилась в конце 90-х годов, соглашение существовало много лет и было твердо установлено (по крайней мере, в мире C ++).

Я не знаю, на какие учебники вы ссылаетесь, но я предполагаю, что они используют соглашение из-за одного из двух факторов:

  • Это учебники по С ++, написанные людьми, привыкшими к соглашению m_, и / или ...
  • Они пишут код в виде простого (моноширинного) текста без подсветки синтаксиса, поэтому соглашение m_ полезно, чтобы сделать примеры понятнее.

Один пример может быть таким: wiki.qt.io/How_to_Use_QSettings Поскольку Qt Creator использует подсветку, может появиться первое предположение. Немного по-другому может быть другое соглашение, использующее _object () для частных объектов класса и p_variable, если это указатель, поскольку оба не подсвечены, как я знаю, и, кажется, имеют смысл использовать его.
— Иванович

3

Lockheed Martin использует схему именования с 3 префиксами, с которой было приятно работать, особенно при чтении чужого кода.

   Scope          Reference Type(*Case-by-Case)   Type

   member   m     pointer p                       integer n
   argument a     reference r                     short   n
   local    l                                     float   f
                                                  double  f
                                                  boolean b

Так...

int A::methodCall(float af_Argument1, int* apn_Arg2)
{
    lpn_Temp = apn_Arg2;
    mpf_Oops = lpn_Temp;  // Here I can see I made a mistake, I should not assign an int* to a float*
}

Возьми это за то, что оно того стоит.


Потрясающие. Спасибо за «пример». Что действительно полезно, так это когда вы редактируете 200 000 строк кода.
— Jiveturkey

1
Не нужно защищаться. Я честно пытаюсь помочь вам, показывая, что в вашем ответе есть ошибка. Позвольте мне быть более ясным, тогда: не имеет значения, если у вас есть 5 или 200 000 строк кода: компилятор не позволит вам выполнить присваивание с несовместимыми типами указателей. Таким образом, пункт, сделанный в комментарии, является спорным.
— Кассио Ренан

Не хотел выходить в обороне. Сожалею.
— Jiveturkey

Это разновидность венгерской нотации, которая не имеет смысла в современных языках ...
— док

2

Чтобы завершить текущие ответы и поскольку вопрос не зависит от языка, некоторые C-проекты используют префикс m_для определения глобальных переменных, специфичных для файла, а также g_для глобальных переменных, у которых область действия больше, чем определяемый ими файл.
В этом случае глобальные переменные, определенные с префиксом, m_ должны быть определены как static.

См. Соглашение по кодированию EDK2 (реализация с открытым исходным кодом UEFI) для примера проекта, использующего это соглашение.


1

Один аргумент, который я еще не видел, заключается в том, что префикс, такой как, m_может использоваться, чтобы предотвратить конфликт имен с #defineмакросом 'd'.

Регулярный поиск #define [a-z][A-Za-z0-9_]*[^(]в /usr/include/term.hcurses / ncurses.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.