Pull to refresh
38
0
Гиляровский Константин @Chaos_Optima

RnD Computer Graphics

Send message
Ответил до редактирования.
Нельзя делать #define NULL whatever в пользовательском коде.

Можно, другое дело что это очень плохо, но тем не менее сделать это можно.
даже не поморщится
liveworkspace.org/code/XjE1O$0
Вызвать можно, но это вызовет ошибку в случае если есть обращение к полям, виртуальным методам, или если сам метод является виртуальным (последние не совсем так но проблемы могут возникнуть).
даже не поморщится
http://liveworkspace.org/code/XjE1O$0
Вызвать можно, но это вызовет ошибку в случае если есть обращение к полям, виртуальным методам, или если сам метод является виртуальным (последние не совсем так но проблемы могут возникнуть).
А кому непонятно? Новичкам разве что, но гадлайны, делаются для разработок в компаниях куда не берут людей которые не знают языка. Обычно за
if(ptr != 0) по рукам бьют т.к. это равносильно if(SomeBool == true) конечно компилятор это разрулит, но обычно это заставляет обращать лишнее внимание на условие.
Ты о чём? писать 0 вместо NULL это UB? мда…
Что и? проблема в том что это можно сделать, и это может повлечь не очевидную проблему (злая шутка)
Поэтому писать 0 всё же лучше, а с точки зрения читаемости это ничего не поменяет.
Вообщето такое возможно но мало вероятно.
SomeClass *lv_Obj = 0; lv_Obj->DoSmth(); // функция вызовется и если внутри нет обращения к полям то ещё и успешно выполнится.

но вообще так писать разуметься не хорошо, а если уж и пишешь то следует писать
if (!this) return;

ибо ненужные скоупы это тоже плохо.
В С++ нет bool это иллюзия есть лишь 0 и не 0 так что там ничего не приводится.
Так почему же зная то, что NULL = 0 — стоит писать 0

как минимум потому что NULL является макросом который можно переопределить.
а в циклах такая запись не естественна?

с циклами я кстати с автором тоже несогласен while (1) гораздо лучше
#define true 0 // happy debugging motherfucker!
Ничего не понял, в чём проблема? Отличить конструктор от метода? помоему это очевидно и с именем никак не пересекается.
и потом, допустим, должно быть SomeClass::Method(), но при этом someClass.method(); же, что еще больше путаницы создает.

в чём конкретно? что трудно различить SomeClass::Method() и SomeClassObj.Method()? А :: и. не помогут? К тому же я вообще ни разу не встречал ситуации когда статический метод и обычный были с одинаковым именем.
ИМХО тут очень, очень много вредных советов.
1. Допускаются любые нарушения рекомендаций, если это улучшает читаемость.

Незя, ибо читаемость за частую очень субъективно.
2. Правила могут быть нарушены, если против них есть персональные возражения.

XD тогда зачем вообще заводить гайдлайни по коду?
Позволяет легко отличать переменные от типов, предотвращает потенциальные коллизии имён, например: Line line;

Всегда думал что наилучший подход в данном случае использовать префиксы видимости (хоть они и не очень нравятся), они очень хорошо помогают в условиях современных IDE с интелесенсом, и при чтении, сравни:

  m_Field = lv_Field + _Offset;
/*
сразу при чтении понятно m_Field - поле класса lv_Field1 - локальная переменная метода _Offset - параметр метода.
при этом нет никаких конфликтов имён, быстро читается + при вводе m_ интелесенс сразу выведет поля также и при lv_ и _
/**/
  field = field1 + offset; // что от чего и где совсем непонятно.


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

Зачем? при этом ведь возможен конфликт имён, и из-за этого тебе потом приходится ставить постфикс в приватных переменных, лучше с большой буквы т.к. это в любом случае будет выглядеть лучше
SomeObj.Method() // гармония SomeObj.method() // дизгармония
7. Названия пространств имён следует записывать в нижнем регистре.

Логика тоже неясна. Зачем дробить понятие наименование на такие группы? когда конфликты в случае namespace, class name, func name. практически никогда не происходят, гораздо лучше задать им единый стиль.
SomeNamespace::SomeObj.Method() // гармония some_namespace::SomeObj.method() // дизгармония
8. Следует называть имена типов в шаблонах одной заглавной буквой.
Это самый вредный совет который только можно было придумать, параметры шаблона, равносильны параметрам функции, тыже небудешь делать в функции такие параметры: void SomeFunc(int A, int C, int B, char* T)
9. Аббревиатуры и сокращения в именах должны записываться в нижнем регистре.

Не имеет смысла аббревиатуры на то и аббревиатуры что имеют определённый стиль написания, и менять его не следует.
11. Членам класса с модификатором private следует присваивать суффикс-подчёркивание.

Суффиксы самая бессмысленная вещь, либо префиксы либо без них. Если приватное имя, и имя параметра будут совпадать, то будет очень легко допустить ошибку при наборе + интелесенс поможет сделать ошибку, а при чтении суффикс _ вообще будет незаметен. Вредный совет.
12. Настраиваемым переменным следует давать то же имя, что и у их типа.

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

SomeFunc(string& stringPath, int CountInt, float OffsetFoloat)

Зачем повторять тип когда IDE сама подскажет?
14. Переменные, имеющие большую область видимости, следует называть длинными именами, имеющие небольшую область видимости — короткими.

название пункта звучит очень гупо. Надо было сказать про стандартное допущение при наименовании итераторов в циклах.
17. Слова get/set должны быть использованы везде, где осуществляется прямой доступ к атрибуту.

Довольно спорный момент, get/set это так называемые свойства, которые в других языках реализованы обычным именем свойства без get/set, да и без get/set облегчается рефакторинг.
18. Слово compute может быть использовано в методах, вычисляющих что-либо.

Зачем?
Дайте читающему сразу понять, что это времязатратная операция.

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

Аналогично с предыдущем высказыванием.
Следует избегать сокращения init.

Почему? Чем оно вредно?
21. Переменным, представляющим GUI, следует давать суффикс, соответствующий имени типа компонента.

Спорно
23. Префикс n следует использовать для представления числа объектов.

Нет смысла, и не очевидно.
28. Следует избегать сокращений в именах.

Почему? Многие сокращения являются общепризнанными, например Avg, Min, Max, Sin, Cos, Cmd, Init и т.д. зачем перегружать названия и делать их длинными когда в некоторых случаях это не несёт смысла.
37. Содержимое файлов не должно превышать 80 колонок.

Спорно, экраны уже давно не такие маленькие.
38. Нельзя использовать специальные символы (например, TAB) и разрывы страниц.

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

ни разу ещё не встречался с подобными проблемами.
40. Заголовочные файлы должны содержать защиту от вложенного включения.

все компиляторы уже давно поддерживают #pragma once зачем прикручивать гуарды непонятно.
51. Символ указателя или ссылки в языке C++ следует ставить сразу после имени типа, а не с именем переменной.

Наоборот, т.к. символ указателя или ссылки в языке C++ относится к переменной а не типу.
53. Следует избегать неявного сравнения булевых (логических) переменных и указателей с нулём.

Глупость, в стандарте С++ и С нет особого типа bool который необходим для условий, соответственно не имеет смысла писать

if (nLines != 0) // в С++ это равносильно if (nLines != false)

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

мда… а в логике работы программ эти выражения не участвуют да?
Если это не указано явно, C++ считает, что возвращаемое значение имеет тип int.

Неужели может попробуешь скомпилировать код с функцией без типа возврата? Такое допускается, только с main и то выдаёт ошибку.
71. Основной отступ следует делать в два пробела.

Табами и только табами, т.к. табы можно настроить в большинстве IDE а пробелы нет.
72. Блоки кода следует оформлять так, как показано в примере 1 (рекомендуется) или в примере 2, но ни в коем случае не так, как показано в примере 3. Оформление функций и классов должно следовать примеру 2.

О да, 1 и 2 являются одним из вечных источников холиваров K&R или Олман в области стиля. И гайдлайн который вроде бы должен как раз такие моменты разруливать включает оба этих момента, круто!
89. Используйте выравнивание везде, где это улучшает читаемость.

ты же говорил что так

if (a == lowValue) compueSomething(); else if (a == mediumValue) computeSomethingElse(); else if (a == highValue) computeSomethingElseYet();

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

В общем очень, очень плохая статья. Многое писал КЭП, много вредных советов, много спорных моментов, много бессмысленных советов, много не освещённых моментов (например макросы, шаблоны, вложенные классы, датахолдеры, употребление explicit, перегрузка операторов, абстрактные классы(они же интерфейсы) ). Очень многое можно выкинуть и упростить.
Принципиальной разницы не появилось, параметры все так же на стеке в обратном порядке, о доступе к массиву элементов речи нет.

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

ещё бы знать как он внутри устроен, я же на угад всё делал.
Ок вот другой вариант, ещё лучше и проще. Тут копируются только указатели.
liveworkspace
(я таких могу ещё кучу придумать)
Элементы в памяти расположены в обратном порядке, как параметры в стеке.

Я просто привёл простейшее решение, можно всё сделать совершенно по другому, просто хотел показать, что чтобы пройтись по элементам std::initializer_list ненужен, и можно написать свой аналог, также как и в случае с std::function.
+ ещё список проблем:

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

ответ тут
Намного посидел вечером и решил разобраться со списками инициализации, в общем std ненужен, вот пруф
liveworkspace
А вот насчёт этого, без понятия, ещё не ковырял, но наверняка это всё также оборачивается в какой-то неопределённый класс + шаблонная магия ))
Подразумевалась альтернатива std::function

ну так я про неё и говорю, написать свою альтернативу, которая принимает лямбду не проблема
Например, лямбда в общем случае может иметь тип только std::function, что лишает разработчика возможности создать альтернативу

на самом деле лямбда это просто класc с переопределённым оператором (), так что если реализовывать свой делегат, то проблем это не вызовет.

Information

Rating
4,664-th
Location
Воронеж, Воронежская обл., Россия
Registered
Activity