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

155

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

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

kravemir
источник
18
Прежде чем бездумно следовать примеру с венгерской нотацией, сделайте небольшую проверку истории того, что на самом деле является венгерская нотация. Потому что называть int iCounter просто бессмысленно. Но разумно называть int xAnnotationPos и ​​yAnnotationPos. Используйте семантическую версию.
АксельК
Иногда импортируемые модули префиксируют функции и переменные, так что вы с меньшей вероятностью перезапишите их своим собственным кодом. Это способ «зарезервировать» имена для конкретного использования.
earthmeLon
3
В то время как «венгерская» нотация часто злобно высмеивается, ее особая разновидность, обозначающая переменную область действия, имеет некоторые реальные преимущества. Помимо определения области действия переменной, он предотвращает конфликты имен, например, когда у local, parm и member все одно и то же намерение и, следовательно, одно и то же «семантическое» имя. Это может сделать обслуживание больших баз кода проще и менее подверженным ошибкам.
Hot Licks
8
Существуют аргументы за и против любого стандарта кодирования, но в вопросе четко задается вопрос, для чего m_, однако половина ответов здесь - это комментарий о том, почему все считают, что их нынешний фаворит - лучший.
cz

Ответы:

108

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

MichaelHouse
источник
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.

InfZero
источник
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 для текущих учеников.

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

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

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

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

  • Это учебники по С ++, написанные людьми, привыкшими к соглашению m_, и / или ...
  • Они пишут код в виде простого (моноширинного) текста без подсветки синтаксиса, поэтому соглашение m_ полезно, чтобы сделать примеры понятнее.
sergut
источник
Один пример может быть таким: 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*
}

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

jiveturkey
источник
Потрясающие. Спасибо за «пример». Что действительно полезно, так это когда вы редактируете 200 000 строк кода.
Jiveturkey
1
Не нужно защищаться. Я честно пытаюсь помочь вам, показывая, что в вашем ответе есть ошибка. Позвольте мне быть более ясным, тогда: не имеет значения, если у вас есть 5 или 200 000 строк кода: компилятор не позволит вам выполнить присваивание с несовместимыми типами указателей. Таким образом, пункт, сделанный в комментарии, является спорным.
Кассио Ренан
Не хотел выходить в обороне. Сожалею.
Jiveturkey
Это разновидность венгерской нотации, которая не имеет смысла в современных языках ...
док
2

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

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

OlivierM
источник
1

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

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

yyny
источник