Есть ли общее соглашение о капитализации в C ++? [закрыто]

13

Я проделал большую работу в Python и Java, и оба эти языка имеют довольно общие (хотя и не универсальные) соглашения о том, как использование заглавных букв в идентификаторах: как PascalCaseдля имен классов, так и ALL_CAPSдля «глобальных» констант, но для других идентификаторов a много кода Java использует, mixedCaseтогда как много кода Python использует underscore_delimiters. Я знаю, что ни один язык или библиотека не обеспечивает какую-либо конкретную прописную букву, но я обнаружил, что, когда я придерживаюсь стандартных соглашений для языка, который я использую, мой код кажется намного более читабельным.

Сейчас я начинаю проект на C ++, и я хотел бы применить ту же идею. Есть ли какое-нибудь наиболее распространенное соглашение о капитализации, о котором я должен знать?

Дэвид З
источник
Проблема с camelCase в том, что он не очень хорошо работает с препроцессором. Не большая проблема, тем более что препроцессора обычно можно избежать.
Пабби
Я должен был принять это решение всего несколько дней назад. В конце концов, это было не сложно, так как стандартная библиотека и boost используют underscore_lowercase_delimiters. Так как я использую boost в качестве ускорителя STL, он будет разбросан по всему моему коду. Другие библиотеки, которые я использую, это PascalCase (SFML), могут быть легче размещены, поэтому любой данный метод является довольно стандартным.
Макс
@ Pubby8: из любопытства: как CamelCase конфликтует с препроцессором?
Иоахим Зауэр
@JoachimSauer Отдельные слова в camelCase могут иметь другой регистр, но макросы не могут изменить регистр. Это становится проблемой, если вам нужен макрос, который принимает часть слова в качестве аргумента - вам может потребоваться указать оба случая в качестве аргументов: macro (x, X). Это довольно незначительная проблема, но следует знать, если вы собираетесь использовать препроцессор.
Пабби

Ответы:

27

Есть ли какое-нибудь наиболее распространенное соглашение о капитализации, о котором я должен знать?

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

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

Однако, что бы вы ни использовали, самое важное правило: будьте последовательны!

Интересно, что хотя я начинал с сочетания PascalCase и camelCase и участвовал в многочисленных проектах с еще более многочисленными соглашениями об именах, я обнаружил, что с годами я все больше и больше застревал с standard_library_convention. Не спрашивай меня почему.

SBI
источник
Спасибо за информацию ... так что стандартная библиотека подчеркивает, тогда? (по крайней мере, больше, чем что-либо еще?) Я размышлял в том же духе, но это было довольно сложно сказать из-за таких вещей, как iostream, в которых половина имен методов, по-видимому, представляет собой тот же самый вид фрагментов слов, что и ANSI C :-P
Дэвид Z
5
@David: Библиотеке iostreams, вероятно, 25 лет, и (за исключением C lib или курса), возможно, самая старая часть C ++ std lib. Надеюсь, никто в здравом уме не спроектирует его таким, каким он является сейчас, и, надеюсь, даже те, кто не в здравом уме, не выберут идентификаторы так, как они используются в библиотеке потоков. (Да ладно, есть функции с именем egptr, sputnи uflowтак же , как underflow. Это просто весело!) Во всяком случае, да, станд Lib в настоящее время использует all_lowercase_with_underscores.
ВОО
@sbi Я узнал, что библиотека iostream больше не считается стандартной библиотекой для C ++. И, как вы упомянули, его идентификаторы бесполезны в качестве соглашения о программировании ;-)
umlcat
2
@umlcat: библиотека iostreams (в ее шаблоне, принятом для C ++ 03) наиболее определенно считается частью стандартной библиотеки C ++.
ВОО
Я тоже пошел тем же путем. Думаю, причина в том, что CamelCase немного легче набрать, и я хотел быть там ленивым. Позже я узнал, что потратил больше времени на чтение и рефакторинг своего кода, чем на его написание, и snake_case легче читать. Так что это все о минимизации затрат энергии. Сейчас я играю с использованием строчных имен для классов. Это нетрадиционно, однако я думаю, что переключение между ними и выделение прописными буквами важных экземпляров и типов нижнего регистра фактически улучшает читабельность моего кода. Я думаю, может быть, это путь. В верхнем регистре, что важно, как в человеческом.
PSkocik
19

Давайте сначала договоримся, что ВСЕ ВЕРХНЯЯ ЧАСТЬ является бельмом на глазу и должна быть сведена к минимуму.

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

В раннем С не было констант, поэтому константы должны были быть выражены как макросы. Кроме того, в те ранние дни программы были намного короче, так что можно было использовать методы, которые сегодня не годятся (например, IIRC Брайан Керниган написал код с большим количеством макросов, не написанных заглавными буквами). Кроме того, в те дни клавиатуры, которые не имели строчных букв, существовали; Я использовал один из них, на норвежском компьютере Tandberg EC-10, примерно в 1980 или 1979 году.

Итак, Java взяла верхний регистр для констант с раннего C. Между тем, и, возможно, даже до этого (я не уверен в хронологии здесь), C получил константы. Однако, хотя, конечно, некоторые / многие программисты на C застряли в более раннем соглашении констант по необходимости в качестве макросов в верхнем регистре, программисты на C ++ были более разумными.

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

Так,

    int const answer = 42;    // Nice, good, OK.
    const int ANSWER = 0x2A;  // Ouch!
    #define COMPANYNAME_ANSWER 052  // Oh kill me, please.

Ну, вы могли подумать, что я упомянул только заглавные клавиши в верхнем регистре. О нет. Потому что это просто самое старое, самое архаичное технологическое ограничение, которое обусловило соглашения об именах или, по крайней мере, повлияло на то, насколько неправильными / правильными они казались. Затем возникла проблема с 7-битной последовательной передачей, которая вызвала соответствующие проблемы с используемыми кодами символов (кодировки символов Newspeak), что означало, что вы должны были ограничить себя буквами английского алфавита, от A до Z.

На самом деле я рекомендую все еще делать это. Вот где мы находимся! У нас нет дальше.

На данный момент, начиная с 2011 года, стандарт C ++ поддерживает общий Unicode в именах (и делает это с 1998 года), в то время как в реальных реализациях C ++ нет. В частности, компилятор g ++ имеет национальный характер. Это связано с технологическими ограничениями средневековья.

Так,

    double blueberryJamViscosity  = 0.0;    // OK
    double blåbærsyltetøyViskositet = 0.0;  // Ouch!

Наконец, на предмет подчеркивания и перемежающиеся заглавные буквы,

  • Зарезервируйте легко узнаваемую форму для имен типов.
  • Зарезервируйте ВСЕ ВЕРХНИЕ ПУНКТЫ для макросов
  • Быть последовательным.

Я думаю, что это действительно так, за исключением таких правил, как «как правило, избегать однобуквенных имен, кроме (loop, template param, blah blah)» и «избегать использования l, легко путать с 1» и «избегать прописных букв O, легко путать с 0 ". Также, конечно, избегайте использования зарезервированных имен, например, начиная с нижнего подчеркивания, за которым следует верхний регистр, содержащий два последовательных подчеркивания, или начиная с подчеркивания и находясь в глобальном пространстве имен.

Ура

Альф П. Штайнбах
источник
Альф, ISTR Stroustrup упоминает в D & E C копирование constиз C ++, так что это должно было произойти очень давно, и задолго до Java, вероятно, для C89.
ВОО
2
О, и сердечный +1для "Будь последовательным!" Читая его, я удивляюсь, почему я забыл упомянуть об этом, самом важном, правиле в своем ответе, когда я никогда не забывал об этом говорить своим ученикам. Я полагаю, вы простите меня, если я сейчас добавлю это в свой ответ в качестве запоздалой мысли?
ВОО
2

Я обычно склонен придерживаться соглашения, которое я вижу больше всего в существующих кодовых базах для языка. В случае C ++ я обычно вижу camelCase. В случае с Ruby или PHP я обычно вижу stuff_like_this.

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

DeM0nFiRe
источник
1

Ну, есть Systems Hungarian, которая действительно распространена даже сейчас, но я бы лучше перерезал себе горло, чем рекомендовал бы это. Apps венгерский язык лучше, так как его аннотативные знаки действительно указывают на семантику, хотя я чувствую, что он слишком увлечен сокращениями, когда подойдет короткое слово. (Чтобы использовать пример с этой страницы Википедии, зачем использовать rwдля строки, когда rowдлина только одного символа? Это не похоже на глобальный дефицит гласных.)

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

Donal Fellows
источник
1

Из того, что я видел, это зависит от проекта.

Встроенные подчеркивания, вероятно, более традиционны / чаще используются в C на Unix. Стандартная библиотека следует за этим , а также, так что это должно почти наверняка будет рассматриваться как по умолчанию, который будет использоваться , если не достаточно существующего кода с помощью другой конвенции абсолютно заставить использовать это другой конвенции.

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

Джерри Гроб
источник
1

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

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

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

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

// instead of a manifest constant
#define HOURS 24

// use const
const int kHours = 24; 

// or enum
enum {
    kHours   = 24,
    kMinutes = 60
};
Билл Дверь
источник
0

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

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

Этот предыдущий ответ SO по связанной теме также может представлять интерес: /programming/228783/what-are-the-rules-about-using-an-underscore-in-ac-identifier

Gnawme
источник
Гм, вы можете использовать то же именование , не используя те же имена ... и если вы действительно хотите , одни и те же имена, вы по- прежнему защищены пространствами имен, например , std::stringпротив gnawme::string.
einpoklum