Зачем использовать префиксы для переменных-членов в классах С++

Много кода С++ использует синтаксические соглашения для разметки переменных-членов. Общие примеры включают

  • m_memberName для публичных пользователей (где публичные члены используются вообще)
  • _memberName для частных пользователей или всех участников.

Другие пытаются принудительно использовать этот- > член всякий раз, когда используется переменная-член.

По моему опыту, большинство более крупных баз кода не могут последовательно применять такие правила.

В других языках эти соглашения гораздо менее распространены. Я вижу это только изредка в Java или С#. Я думаю, что никогда не видел его в Ruby или Python. Таким образом, по-видимому, существует тенденция, когда более современные языки не используют специальную разметку для переменных-членов.

Является ли это соглашение еще полезным сегодня на С++ или это просто анахронизм. Тем более, что он так непоследовательно используется через библиотеки. Разве другие языки не показали, что можно обойтись без префиксов членов?

Ответ 1

Вы должны быть осторожны с использованием верхнего подчеркивания. Поддержанное подчеркивание перед заглавной буквой в слове зарезервировано. Например:

_foo

_L

- все зарезервированные слова, а

_foo

_l

нет. Существуют и другие ситуации, когда недопустимые символы подчеркивания перед строчными буквами не допускаются. В моем конкретном случае я обнаружил, что _L был зарезервирован Visual С++ 2005, и столкновение создало неожиданные результаты.

Я нахожусь на заборе о том, насколько полезно указывать локальные переменные.

Вот ссылка, по которой зарезервированы идентификаторы: Каковы правила использования подчеркивания в идентификаторе С++?

Ответ 2

Я все в пользу префиксов , сделанных хорошо.

Я думаю, что (система) венгерская нотация несет ответственность за большую часть "плохого рэпа", который префиксы получают.

Эти обозначения в значительной степени бессмысленны в строго типизированных языках, например. в С++ "lpsz", чтобы сообщить вам, что ваша строка является длинным указателем на строку с нулевым завершением, когда: сегментированная архитектура - это древняя история, строки С++ - это обычные указатели на классы с nul-terminated char, и это не совсем все что трудно понять, что "customerName" является строкой!

Однако я использую префиксы для указания использования переменной (по существу, "Apps Hungarian", хотя я предпочитаю избегать термина венгерский из-за его плохой и несправедливой связи с System Hungarian), и это очень удобный сэкономить время и снижать уровень ошибок.

Я использую:

  • m для участников
  • c для констант /readonlys
  • p для указателя (и pp для указателя на указатель)
  • v для volatile
  • s для статического
  • я для индексов и итераторов
  • e для событий

Если я хочу очистить тип, я использую стандартные суффиксы (например, List, ComboBox и т.д.).

Это заставляет программиста знать об использовании переменной всякий раз, когда они видят/используют ее. Вероятно, самым важным случаем является "p" для указателя (потому что использование изменяется с var на var- > , и вы должны быть гораздо более осторожны с указателями - NULL, арифметикой указателей и т.д.), Но все остальные очень удобны.

Например, вы можете использовать одно и то же имя переменной несколькими способами в одной функции: (здесь пример С++, но он применим в равной степени ко многим языкам)

MyClass::MyClass(int numItems)
{
    mNumItems = numItems;
    for (int iItem = 0; iItem < mNumItems; iItem++)
    {
        Item *pItem = new Item();
        itemList[iItem] = pItem;
    }
}

Вы можете посмотреть здесь:

  • Отсутствие путаницы между элементом и параметром
  • Отсутствие путаницы между индексом/итератором и элементами
  • Использование набора четко связанных переменных (список элементов, указатель и индекс), которые избегают многих ошибок общих (неопределенных) имен, таких как "count", "index".
  • Префиксы уменьшают типизацию (короче и лучше работают с автозавершением), чем альтернативы типа "itemIndex" и "itemPtr"

Еще одна отличная точка итераторов "iName" заключается в том, что я никогда не индексирую массив с неправильным индексом, и если я копирую цикл внутри другого цикла, мне не нужно рефакторировать одну из переменных индекса цикла.

Сравните этот нереально простой пример:

for (int i = 0; i < 100; i++)
    for (int j = 0; j < 5; j++)
        list[i].score += other[j].score;

(который трудно читать и часто приводит к использованию "i", где предназначался "j" )

с:

for (int iCompany = 0; iCompany < numCompanies; iCompany++)
    for (int iUser = 0; iUser < numUsers; iUser++)
       companyList[iCompany].score += userList[iUser].score;

(что намного читаемо и устраняет всю путаницу по индексированию. С автозаполнением в современных IDE это также быстро и легко печатается)

Следующее преимущество заключается в том, что фрагменты кода не требуют понимания какого-либо контекста. Я могу скопировать две строки кода в электронную почту или документ, и любой, кто читает этот фрагмент, может отличить все члены, константы, указатели, индексы и т.д. Мне не нужно добавлять "о, и будьте осторожны, потому что" data "является указателем на указатель", потому что он называется "ppData".

И по той же причине мне не нужно выводить глаза из строки кода, чтобы понять это. Мне не нужно искать код, чтобы определить, являются ли "данные" локальным, параметром, членом или константой. Мне не нужно двигать рукой к мыши, чтобы я мог навести указатель на "данные", а затем дождаться всплывающей подсказки (которая иногда никогда не появляется). Поэтому программисты могут читать и понимать код значительно быстрее, потому что они не тратят время на поиск вверх и вниз или ждут.

(Если вы не думаете, что тратите время на поиски вверх и вниз, чтобы найти работу, найдите код, который вы написали год назад, и не смотрели поскольку. Откройте файл и прыгайте примерно на полпути вниз, не читая его. Посмотрите, как далеко вы можете прочитать с этого момента, прежде чем не знаете, если что-то является членом, параметром или локальным. Теперь перейдите к другому случайному место... Это то, что мы все делаем весь день, когда мы одиноки переступая через код другого пользователя или пытающийся понять, как вызов их функции)

Префикс 'm' также позволяет избежать (IMHO) уродливой и многословной "this- > " нотации и непоследовательности, которую он гарантирует (даже если вы будете осторожны, вы, как правило, получите смесь "this- > data 'и' data 'в том же классе, потому что ничто не обеспечивает последовательное написание имени).

'this' обозначение предназначено для устранения двусмысленности - но почему кто-то намеренно пишет код, который может быть неоднозначным? Неоднозначность рано или поздно приведет к ошибке. И в некоторых языках 'this' не может использоваться для статических членов, поэтому вам нужно ввести" особые случаи" в вашем стиле кодирования. Я предпочитаю иметь одно простое правило кодирования, которое применяется везде - явное, недвусмысленное и последовательное.

Последнее важное преимущество - Intellisense и автозаполнение. Попробуйте использовать Intellisense в форме Windows, чтобы найти событие - вам нужно прокрутить сотни таинственных методов базового класса, которые вам никогда не нужно будет вызывать, чтобы найти события. Но если каждое событие имеет префикс "e" , они автоматически будут перечислены в группе под "e" . Таким образом, префикс работает для группировки членов, констант, событий и т.д. В списке intellisense, что позволяет быстрее и легче находить имена, которые вы хотите. (Обычно метод может иметь около 20-50 значений (locals, params, members, consts, events), которые доступны в его области. Но после ввода префикса (я хочу использовать индекс сейчас, поэтому я набираю "i"... '), мне присваивается только 2-5 автозаполнения. Люди, добавочные для набора текста, префиксы и значащие имена резко сокращают пространство поиска и значительно ускоряют скорость разработки)

Я ленивый программист, и вышеупомянутая конвенция спасает меня от большой работы. Я могу быстрее закодировать код, и я делаю гораздо меньше ошибок, потому что знаю, как использовать каждую переменную.


Аргументы против

Итак, каковы минусы? Типичными аргументами против префиксов являются:

  • "Префиксные схемы плохие/злые". Я согласен с тем, что "m_lpsz" и его аналоги плохо продуманы и совершенно бесполезны. Поэтому я бы посоветовал использовать хорошо продуманную нотацию, предназначенную для поддержки ваших требований, а не копирование чего-то, что не подходит для вашего контекста. (Используйте подходящий инструмент для задания).

  • "Если я изменил использование чего-то, что мне нужно переименовать". Да, конечно, вы знаете, что такое рефакторинг, и почему у IDE есть инструменты для рефакторинга, чтобы быстро и безболезненно выполнять эту работу. Даже без префиксов изменение использования переменной почти наверняка означает, что ее имя должно быть изменено.

  • "Префиксы просто путают меня". Как и каждый инструмент, пока вы не научитесь его использовать. Как только ваш мозг привык к шаблонам именования, он автоматически отфильтрует информацию, и вы не будете иметь в виду, что префиксы уже есть. Но вы должны использовать схему, подобную этому, в течение недели или двух, прежде чем вы действительно начнете "свободно". И это, когда многие люди смотрят на старый код и начинают задаваться вопросом, как они когда-либо управлялись без хорошей префиксной схемы.

  • "Я могу просто посмотреть на код, чтобы работать с этим материалом". Да, но вам не нужно тратить время на поиск в другом месте кода или запоминание каждой мелочи, когда ответ прямо на месте, ваш глаз уже сосредоточен.

  • (Некоторые из них) эту информацию можно найти, просто ожидая всплывающей подсказки для моей переменной. Да. Где поддерживается, для некоторых типов префикса, когда ваш код компилируется чисто, после ожидания, вы можете прочитать описание и найти информацию, которую префикс передал бы мгновенно. Я считаю, что префикс - это более простой, надежный и эффективный подход.

  • "Это больше печатает". В самом деле? Один цельный персонаж больше? Или это - с инструментами автоматического завершения IDE, это часто сокращает набор, поскольку каждый префикс значительно сужает пространство поиска. Нажмите "e" , и три события в вашем классе появятся в intellisense. Нажмите "c" и перечислены пять констант.

  • "Я могу использовать this-> вместо m". Ну, да, вы можете. Но это всего лишь уродливый и более подробный префикс! Только он несет гораздо больший риск (особенно в командах), потому что компилятор является необязательным, и поэтому его использование часто несовместимо. m, с другой стороны, является кратким, ясным, явным и необязательным, поэтому гораздо труднее делать ошибки, используя его.

Ответ 3

Обычно я не использую префикс для переменных-членов.

Я использовал префикс m, пока кто-то не заметил, что "у С++ уже есть стандартный префикс для доступа к члену: this->.

Итак, что я сейчас использую. То есть, когда есть двусмысленность, я добавляю префикс this->, но обычно нет никакой двусмысленности, и я могу просто ссылаться непосредственно на имя переменной.

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

Конечно, очевидный счетчик это "да, но тогда вы не можете сразу увидеть, является ли переменная членом класса или нет".

К чему я говорю "ну и что? Если вам нужно это знать, ваш класс, вероятно, имеет слишком много состояний. Или функция слишком большая и сложная".

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

И лучше всего, это последовательно! Мне не нужно делать ничего особенного или помнить о любых соглашениях, чтобы поддерживать согласованность.


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

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

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

Так что проще просто избегать подчеркивания. Используйте postfix underscore или префикс m_ или просто m, если вы хотите кодировать область видимости в имени переменной.

Ответ 4

Я предпочитаю подчеркивания подчеркивания, например:

class Foo
{
   private:
      int bar_;

   public:
      int bar() { return bar_; }
};

Ответ 5

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

void set_foo(int foo) { foo = foo; }

Это не работает, разрешено только одно foo. Итак, ваши варианты:

  • this->foo = foo;

    Мне это не нравится, поскольку он вызывает затенение параметров, вы больше не можете использовать предупреждения g++ -Wshadow, а также более длинный тип, чем m_. Вы также по-прежнему сталкиваетесь с конфликтами имен между переменными и функциями, когда у вас есть int foo; и int foo();.

  • foo = foo_; или foo = arg_foo;

    Используется это некоторое время, но это приводит к тому, что списки аргументов уродливы, документация не должна иметь дело с неоднозначностью имени в реализации. Здесь также существуют конфликты имен между переменными и функциями.

  • m_foo = foo;

    Документация API остается чистой, вы не получаете двусмысленности между функциями-членами и переменными и ее более короткий тип, чем this->. Единственным недостатком является то, что структуры POD уродливы, но поскольку структуры POD не страдают от двусмысленности имени в первую очередь, им не нужно использовать их с ними. Наличие уникального префикса также упрощает несколько операций поиска и замены.

  • foo_ = foo;

    Большинство преимуществ m_ применимы, но я отклоняю его по эстетическим соображениям, конечное или ведущее подчеркивание просто заставляет переменную выглядеть неполной и неуравновешенной. m_ просто выглядит лучше. Использование m_ также более расширяемо, так как вы можете использовать g_ для globals и s_ для статики.

PS: Причина, по которой вы не видите m_ в Python или Ruby, состоит в том, что оба языка используют собственный префикс, Ruby использует @ для переменных-членов, а для Python требуется self..

Ответ 6

Я не могу сказать, насколько это широко распространено, но, говоря лично, я всегда (и всегда) префиксные мои переменные-члены 'm'. Например:.

class Person {
   .... 
   private:
       std::string mName;
};

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

Ответ 7

При чтении через функцию-член, знание того, кто "владеет" каждой переменной, абсолютно необходимо для понимания значения переменной. В такой функции:

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

... достаточно легко увидеть, откуда берутся яблоки и бананы, но как насчет винограда, дынь и капель? Должны ли мы искать глобальное пространство имен? В объявлении класса? Является ли переменная членом этого объекта или членом этого класса объектов? Не зная ответа на эти вопросы, вы не можете понять код. И в более длинной функции даже декларации локальных переменных, таких как яблоки и бананы, могут потеряться в тасовании.

Предоставление согласованной метки для глобальных переменных, переменных-членов и статических переменных-членов (возможно, g_, m_ и s_ соответственно) мгновенно разъясняет ситуацию.

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

Вначале это может занять некоторое время, но потом, что в программировании нет? Был день, когда даже {и} выглядели странно для вас. И как только вы привыкнете к ним, они помогут вам понять код намного быстрее.

(Использование "this- > " вместо m_ имеет смысл, но еще более затянуто и визуально разрушительно. Я не рассматриваю его как хорошую альтернативу для разметки всех видов использования переменных-членов.)

Возможное возражение против вышеуказанного аргумента будет заключаться в расширении аргумента до типов. Также может быть правдой, что знание типа переменной "абсолютно необходимо для понимания значения переменной". Если это так, почему бы не добавить префикс к каждому имени переменной, который идентифицирует его тип? С этой логикой вы получаете венгерскую нотацию. Но многие люди считают, что венгерская нотация кропотливая, уродливая и бесполезная.

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

Венгерский расскажет нам что-то новое о коде. Теперь мы понимаем, что в Foo:: bar() есть несколько неявных отбросов. Теперь проблема с кодом заключается в том, что значение информации, добавленной венгерскими префиксами, невелико относительно визуальной стоимости. Система типа С++ включает в себя множество функций, помогающих типам хорошо работать вместе или поднять предупреждение или ошибку компилятора. Компилятор помогает нам справляться с типами - нам не нужны обозначения для этого. Мы можем сделать вывод, что переменные в Foo:: bar(), вероятно, являются числовыми, и если это все, что мы знаем, это достаточно хорошо для получения общего понимания функции. Поэтому значение знания точного типа каждой переменной относительно невелико. Тем не менее уродство переменной типа "s_dSpuds" (или даже просто "dSpuds" ) велико. Таким образом, анализ затрат и результатов отвергает венгерскую нотацию, тогда как преимущество g_, s_ и m_ превосходит затраты в глазах многих программистов.

Ответ 8

Основной причиной для префикса участника является разграничение между функцией-членом и переменной-членом с тем же именем. Это полезно, если вы используете геттеры с именем вещи.

Рассмотрим:

class person
{
public:
    person(const std::string& full_name)
        : full_name_(full_name)
    {}

    const std::string& full_name() const { return full_name_; }
private:
    std::string full_name_;
};

В этом случае переменная-член не может называться full_name. Вам нужно переименовать функцию-член в get_full_name() или каким-то образом украсить переменную-член.

Ответ 9

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

Единственная точка, в которой я нахожу такие правила интересными, - это когда мне нужны две вещи с именами одинаковые, например:

void myFunc(int index){
  this->index = index;
}

void myFunc(int index){
  m_index = index;
}

Я использую его, чтобы различать два. Также, когда я переношу вызовы, например, из Windows Dll, RecvPacket (...) из Dll может быть заключен в RecvPacket (...) в моем коде. В этих особых случаях использование префикса типа "_" может привести к тому, что оба будут похожи друг на друга, легко определить, что является, но отличается для компилятора

Ответ 10

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

Я знаю программистов, которым неудобно использовать локальные объявления; они предпочитают размещать все объявления в верхней части блока (как в C), поэтому они знают, где их найти. Я обнаружил, что там, где это допускается, объявление переменных, в которых они впервые используются, уменьшает время, которое я трачу на поиск назад, чтобы найти объявления. (Это верно для меня даже для небольших функций.) Это облегчает мне понимание кода, на который я смотрю.

Я надеюсь, что это достаточно ясно, как это относится к соглашениям об именах участников: когда члены единообразно префиксны, мне никогда не приходится оглядываться назад; Я знаю, что декларация даже не будет найдена в исходном файле.

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

Ответ 11

Другие пытаются обеспечить использование this- > , когда член используется переменная

Это обычно потому, что нет префикса. Компилятор нуждается в достаточной информации для разрешения рассматриваемой переменной, будь то уникальное имя из-за префикса или с помощью ключевого слова this.

Итак, да, я думаю, что префиксы по-прежнему полезны. Я, например, предпочитаю вводить "_" для доступа к члену, а не к "этому → ".

Ответ 12

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

Ответ 13

Другие языки будут использовать условные обозначения кодировки, они просто отличаются друг от друга. Например, у С# есть, вероятно, два разных стиля, которые люди склонны использовать, либо один из методов С++ (_variable, mVariable или другой префикс, например, венгерская нотация), или то, что я называю методом StyleCop.

private int privateMember;
public int PublicMember;

public int Function(int parameter)
{
  // StyleCop enforces using this. for class members.
  this.privateMember = parameter;
}

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

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

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

Ответ 14

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

Ответ 15

ИМО, это личное. Я не помещаю никаких префиксов. В любом случае, если код имеет смысл быть публичным, я думаю, что он должен иметь некоторые префиксы, поэтому он может быть более читаемым.

Часто крупные компании используют его собственные так называемые "правила разработчика".
Кстати, самый забавный, но самый умный, которого я видел, был DRY KISS (Dont Repeat Yourself. Keep It Simple, Stupid).: -)

Ответ 16

Как уже говорили другие, важно быть разговорным (адаптировать стили и обозначения именования к базе кода, в которой вы пишете) и быть последовательными.

В течение многих лет я работал над большой базой кода, которая использует как соглашение "this- > ", так и использование примечания postfix underscore для переменных-членов. На протяжении многих лет я также работал над небольшими проектами, некоторые из которых не имели никакого соглашения об именах переменных-членов и других, которые отличались соглашениями об именах переменных-членов. Из тех небольших проектов я последовательно нашел те, у кого не было никакого соглашения, было самым трудным для быстрого перехода и понимания.

Я очень анально-ретентивен в отношении именования. Я буду мучиться над именем, которое должно быть приписано классу или переменной до такой степени, что, если я не могу придумать что-то, что, по моему мнению, "хорошо", я буду называть его чем-то бессмысленным и представить комментарий, описывающий, что это на самом деле является. Таким образом, по крайней мере, это имя означает то, что я имею в виду - ничего больше и не меньше. И часто, после использования его на некоторое время, я обнаруживаю, что имя должно быть действительно и может вернуться и изменить или реорганизовать соответствующим образом.

Один последний вопрос по теме IDE, выполняющего эту работу, - все это хорошо и хорошо, но IDE часто недоступны в средах, где я выполняю наиболее срочную работу. Иногда единственное, что доступно в этот момент, - это копия "vi". Кроме того, я видел много случаев, когда завершение кода IDE распространяло тупость, например неправильное написание в именах. Таким образом, я предпочитаю не полагаться на костыль IDE.

Ответ 17

Исходная идея для префиксов для переменных-членов С++ заключалась в том, чтобы хранить дополнительную информацию о типе, о которой компилятор не знал. Так, например, у вас может быть строка с фиксированной длиной символов, а другая - с этой переменной и заканчивается символом "\ 0". Для компилятора они оба char *, но если вы попытаетесь скопировать один на другой, вы получите огромные проблемы. Итак, с головы,

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

где "asz" означает, что эта переменная "строка ascii (с нулевым завершением) и" arr "означает, что эта переменная является символьным массивом.

Затем происходит волшебство. Компилятор будет полностью доволен этим утверждением:

strcpy(arrWilma, aszFred);

Но вы, как человек, можете посмотреть на него и сказать "эй, эти переменные на самом деле не такие же, я не могу этого сделать".

К сожалению, многие места используют такие стандарты, как "m_" для переменных-членов, "i" для целых чисел, независимо от того, как они используются, "cp" для указателей char. Другими словами, они дублируют то, что знает компилятор, и делают код очень трудным для чтения одновременно. Я считаю, что эта пагубная практика должна быть запрещена законом и подвержена суровым наказаниям.

Наконец, есть две точки, которые я должен упомянуть:

  • Разумное использование функций С++ позволяет компилятору знать информацию, которую вы должны были кодировать в необработанных переменных стиля C. Вы можете создавать классы, которые позволят только действительные операции. Это должно быть сделано как можно практичнее.
  • Если ваши блоки кода настолько длинны, что вы забудете, какой тип переменной перед использованием, они слишком длинны. Не используйте имена, реорганизовывайте.

Ответ 18

Наш проект всегда использовал "его" как префикс для данных членов, а "the" - как префикс для параметров, без префикса для локальных пользователей. Это немного странно, но оно было принято ранними разработчиками нашей системы, потому что они видели, что она использовалась в качестве конвенции некоторыми коммерческими исходными библиотеками, которые мы использовали в то время (либо XVT, либо RogueWave - возможно, оба). Итак, вы получите что-то вроде этого:

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

Большая причина, по которой я вижу префиксы для определения области видимости (и не другие - я ненавижу венгерскую нотацию), заключается в том, что она мешает вам попасть в беду, написав код, в котором, как вы думаете, вы ссылаетесь на одну переменную, но вы действительно ссылаетесь к другой переменной с тем же именем, что и в локальной области. Он также избегает проблемы придумывания имен переменных для представления той же концепции, но с разными областями, как, например, в примере выше. В таком случае вам придётся придумать какой-либо префикс или другое имя для параметра "theName" - почему бы не сделать последовательное правило, которое применяется повсюду.

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

Что касается самого/самого себя - я честно считаю, что его легче набирать, чем подчеркивания (как машинка для прикосновений, я избегаю подчеркивания, когда это возможно, слишком сильно растягивая домашние строки), и я считаю его более читаемым, чем таинственный подчеркивания.

Ответ 19

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

Учитывая, что они часто объявляются далеко от того, где они используются, я нахожу, что соглашения об именах для глобальных констант (и глобальные переменные, хотя ИМО там редко когда-либо нуждаются в их использовании) имеют смысл. Но в остальном я не вижу большой необходимости.

Тем не менее, я использовал знак подчеркивания в конце всех членов частного класса. Поскольку все мои данные являются частными, это означает, что участники имеют завершающий символ подчеркивания. Обычно я не делаю этого больше в новых базовых кодах, но поскольку, как программист, вы в основном работаете со старым кодом, я все еще делаю это много. Я не уверен, что моя терпимость к этой привычке исходит из того факта, что я всегда делал это всегда и все еще делаю это регулярно или действительно ли это имеет больше смысла, чем маркировка переменных-членов.

Ответ 20

Я использую его, потому что VС++ Intellisense не может сказать, когда показывать частные члены при доступе к классу. Единственным признаком является небольшой символ "блокировки" на значке поля в списке Intellisense. Это упрощает идентификацию частных членов (полей). Кроме того, привычка с С# быть честной.

class Person {
   std::string m_Name;
public:
   std::string Name() { return m_Name; }
   void SetName(std::string name) { m_Name = name; }
};

int main() {
  Person *p = new Person();
  p->Name(); // valid
  p->m_Name; // invalid, compiler throws error. but intellisense doesn't know this..
  return 1;
}

Ответ 21

В python ведущие двойные подчеркивания используются для эмуляции частных членов. Подробнее см. этот ответ

Ответ 22

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

Ответ 23

Код Complete рекомендует m_varname для переменных-членов.

Хотя я никогда не думал, что нотация m_ полезна, я бы дал вес Макконнелла в построении стандарта.

Ответ 24

Я почти никогда не использую префиксы перед именами переменных. Если вы используете достаточно приличную IDE, вы должны иметь возможность рефакторировать и находить ссылки легко. Я использую очень четкие имена и не боюсь иметь длинные имена переменных. У меня никогда не было проблем с этой философией.

Единственный раз, когда я использую префикс, будет в строке подписи. Я префикс параметров для метода с _, поэтому я могу запрограммировать защиту вокруг них.

Ответ 25

Вам не нужен такой префикс. Если такой префикс предлагает вам какие-либо преимущества, ваш стиль кодирования в целом нуждается в исправлении, а не префикс, который не дает вашему коду быть четким. Типичные имена плохой переменной включают "другие" или "2". Вы не исправляете это, требуя, чтобы он был другим, вы исправляете это, заставляя разработчика задуматься о том, что эта переменная делает там в контексте этой функции. Возможно, он имел в виду remoteSide, newValue или secondTestListener или что-то в этой области.

Это эффективный анахронизм, который все еще распространялся слишком далеко. Прекратите префикс ваших переменных и дайте им правильные имена, чья ясность отражает, как долго они используются. До 5 строк вы можете назвать это "i" без путаницы; более 50 строк вам нужно довольно длинное имя.

Ответ 26

Мне нравятся имена переменных, которые дают только значение для значений, которые они содержат, и оставляют, как они объявлены/реализованы вне имени. Я хочу знать, что означает значение, период. Возможно, я сделал больше, чем средний объем рефакторинга, но я считаю, что внедрение того, как что-то реализовано в названии, делает рефакторинг более утомительным, чем нужно. Префиксы, указывающие, где и как объявляются члены объекта, являются специфичными для реализации.

color = Red;

В большинстве случаев мне все равно, что Red - это перечисление, структура или что-то еще, и если функция настолько велика, что я не могу вспомнить, был ли цвет объявлен локально или является членом, возможно, время, чтобы разбить функцию на более мелкие логические единицы.

Если ваша циклическая сложность настолько велика, что вы не можете следить за тем, что происходит в коде, не имея специальных указаний, встроенных в имена вещей, скорее всего, вам нужно уменьшить сложность вашей функции/метода.

В основном, я использую 'this' в конструкторах и инициализаторах.

Ответ 27

Я использую переменные m_ для переменных-членов, чтобы использовать Intellisense и связанные с ними IDE-функции. Когда я кодирую реализацию класса, я могу набрать m_ и увидеть выпадающее поле со всеми членами m_, сгруппированными вместе.

Но я мог бы жить без m_ без проблем, конечно. Это просто мой стиль работы.

Ответ 28

В соответствии с СТАНДАРТАМИ КОДИРОВАНИЯ СОВМЕСТНОГО БОРЬБЫ С БОЙНЫМ ВОЗДУХОМ C++ (декабрь 2005 г.):

AV Правило 67

Публичные и защищенные данные должны использоваться только в структуры - не классы. Обоснование: класс способен поддерживать инвариант, контролируя доступ к своим данным. Тем не менее, класс не может контролировать доступ к своим членам, если эти члены не являются частными. Отсюда все данные в классе должны быть конфиденциальными.

Таким образом, префикс "m" становится бесполезным, поскольку все данные должны быть конфиденциальными.

Но это хорошая привычка использовать префикс p перед указателем, так как это опасная переменная.

Ответ 29

Многие из тех соглашений от времени без сложных редакторов. Я бы порекомендовал использовать правильную IDE, которая позволяет раскрашивать любые переменные. Цвет гораздо легче определить, чем любой префикс.

Если вам необходимо получить еще больше подробностей о переменной, любая современная среда IDE сможет показать ее вам, переместив курсор или курсор на нее. И если вы используете переменную неправильно (например, указатель с оператором.), Вы все равно получите ошибку.