Comments 109
Спасибо за линк. Сейчас как раз начал потихоньку осваивать кумль — очень в тему,
Рискну предположить, что virtual должен показывать, что метод может быть переопределен в подклассах вашего класса. Если вы не планируете, что от вашего класса будут наследоваться, то писать virtual не следует. Поскольку ваш класс уже наследован от другого класса с виртуальным методом, метод в вашем классе будет виртуальным в любом случае. Кстати, Qt Creator (официальная среда разработки для Qt) показывает виртуальные методы курсивом, так что наглядность не страдает.
Т.е. постулат следует читать так...?
В этом постулате все предельно просто — главное не писать `virtual` перед названием переопределяемого метода в .h файле, если вы наследуете один из классов Qt.
Нет, классы Qt тут ни при чем. Скорее так: «если не предполагается, что этот метод может быть переопределен в подкласах вашего класса».
Откуда такая глубокая мудрость может быть у автора класса? Т.е. если метод изначально был виртуальным уже в базовом классе, то что заставляет твердо верить, что его никто не будет переопределять после вас?
Я говорю в разрезе повторно используемого кода (например, вами же, но через полгода).
Еще раз: мое удивление вызвал «постулат №8» тем, что действительно полезное (ОК — пусть только в ряде случаев) слово virtual «запрещается» писать. Очень хочется понять причину этого «запрета» — чем это слово вредит-то?
Остальные «постулаты» можно как-то обосновать (хотя и с ними иногда тянет поспорить). Но этот — вообще за гранью моего понимания.

P.S. По поводу правила «Публичные классы должны начинаться с буквы ‘Q’ ». Была такая замечательная книжка Голуба «Правила программирования на С++». И там этот же аспект рассматривался с точки зрения библиотеки MFC (где, как известно, все публичные классы начинались с буквы 'C' — «class»). Почти дословно: «Если вы назовете свой класс по этому правилу, а в следующей версии MFC Microsoft выпустит свой класс с таким же именем, угадайте — кому придется менять код?».
Насчет пункта со словом virtual — это отдельная тема.

А говоря про «Публичные классы должны начинаться с буквы ‘Q’ » — это было написано в разрезе контрибьютинга. Если вы работая в Qt хотите назвать класс на Q — следует поменять название.
Честно говоря, я не самый ярый фанат неймспейсов в этом плане. Как по мне лучше назвать класс QcsClass, чем Library::QClass.
Я не вижу зла в том, чтобы напомнить лишний раз людям — метод виртуальный.
А вот если вы соблюдаете правила по написанию имен из Qt, то определить сходу для незнакомого метода его полиморфность — на мой взгляд, дорогого стоит. Особенно для того человека, который чуть позже будет наследовать класс от вашего, а не от базового из Qt.

Кстати, а для виртуальных деструкторов это правило действует? Там тоже слово virtual чем-то мешает?
Тоже возник вопрос по 8 постулату, всегда пишу virtual, что бы отличать, что метод от базового класса
Ну придумали они так, совершенно никакого смысла в этом нет. В C++11 предпочтительно использовать override, и отказаться от virtual в имени ибо будет уже избыточно.
Override совсем про другое и может быть применен если метод не виртуальный.
UFO landed and left these words here
Кажется, постулат 7 в статье выглядит немного не так, как Вы задумывали… Вы наверное имели ввиду это?
Хотя как мне кажется если параметров много то лучше вообще каждый параметр переносить на новую строку…
Очень напрягает, что в каждом фреймворке или библиотеке свой стиль написания. Особенно если с несколькими библиотеками работают в одном месте.
В PHP сейчас работают над единым PSR-2. Пока что приняли только PSR-0.
Замечательно тем, кто использует только один фреймворк. Вот я например, использую для дева софта только Qt — и в полном восторге от Qt Coding Style.
А как можно один фреймворк/библиотеку использовать?
Вот допустим вы решили использовать FANN вместе с Qt.
Опа: разные стили написания.
Угу, а что делать если вдруг решили использовать другоя язык (например Delphi), опа; разный синтаксис… Использование только одного языка/фреймворка — это нормально.
Нормально для проекта какого уровня? Qt слишком слабый фреймворк, чтобы довольствоваться лишь им. Вообще, те кто пишут на C++, как правило, используют несколько фреймворков.
Выражение «Qt слишком слабый фреймворк» строго говоря, не очень точно. Qt — достаточно мощный фреймворк. Но он, конечно же, не универсальный и иногда вместе с ним нужно использовать и другие библиотеки. Тогда, конечно, разных стилей не избежать. Другое дело, что в больших проектах работа делиться между разработчиками (или командами) и тогда вполне может быть, что один человек пишет свою часть только на Qt в стиле Qt, а другой работает над какой-то другой библиотекой в её стиле. Смешение стилей возникает только на стыке этих компонентов, но этот стык, при правильной архитектуре, не такой уж и большой, так что можно жить.
Мощный в чем? В раздутости? Да, согласен. В эффективности и функционале? Увольте.
RegExp до Qt5 был убог до невозможности.
QNetwork в WIndows построен не на comepletion port
XSLT все в экспериментах.
И т.д. Я не могу вспомнить всё сразу, только самое яркое.
Qt отличный GUI framework не для слабых душой(ибо покостылить придется знатно) в котором остальные части билиотеки, как правило, уступают своим аналогам, специализирующимся на конкрентных вещах.
Я вообще-то согласился с Вами на счёт необходимости использования сторонних библиотек.
Ну как сказать, У меня на компе валяется 40 000 кода С++ движка (в процессе разработки), который вообще без фреймворков написан. И жить хуже от того не стало. Хотя нет, вру, он для редактора уровней тянет за собой Qt, но по умолчанию, для самой игры он там не нужен будет.

Qt — очень сильный и качественный фреймворк. Даже не знаю, почему вы его называете слабым… Объясните?

Вообще, те кто пишут на C++, как правило, используют несколько фреймворков.
Нет такого правила)). И мне кажется, что если у вас есть такая статистика — скорей всего она основана на нерепрезентативной выборке.
Если Вы написали 40000 без фреймворков, не значит, что нельзя было написать 10000 с оными. Тут не о чем говорить, я Вашего кода не видел. Но те, кто пишут 40к без, хотя бы, буста вызывают у меня подозрение.
Тем более без boost. Логика такова, что в случае наличия какого либо дефекта, с высокой долей вероятности нужно будет спускаться до самых низов. При использовании boost низами будут исходники boost, от чтения которых люди впадают в депрессию.

К тому же, классы контейнеров с нужными алгоритмами, type traits, in-place constructor и прочими весомо полезными фичами весят 2000-3000 строк кода. Сеть для разных платформ еще 1000-2000. Потоки около тысячи… В общем, не все так печально. Все достаточно быстро и выигрыш при boost-е был бы порядка 10 000 строк кода, 1-2 месяца, что не является очень высокой платой за счастье.

Другими словами, в этом проекте построен микрофреймворк Gaia, который;
1. На порядки меньше буста
2. В среднем не медленне буста.
3. Очень легко читается и дебажится.
4. Лишен мусора.
Не забудьте добавить: протестирован на порядки меншье буста.
Использовать велосипеды это конечно прикольно, но, на моей практике, ни разу себя не оправдало. Может у Вас другая практика, тогда я рад за Вас.

P.S. Непонимание внутренностей буста интересная отговорка, сколько им пользуюсь а внутрь лезть приходилось не часто. И дебажить мне его не надо, благо для этого есть сотни тысяч «тестеров».
Скорей всего дефектов больше, чем в бусте. Но, с высокой долей вероятности, в целом в программе меньше дефектов, чем было бы при использовании буста. С бустом у меня проблем особо не возникало, но гордится хотябы 10% процентом понимания буста я не могу. И время затреченное на то, чтобы получить это понимае, подозреваю было бы большим нежели написание собственного фреймворка.

Я являюсь участником проекта, не лидером. Лидер работает сейчас в Ubisoft, игры которого сделаны на С++ без boost.
Ходят слухи, что в gamedev наиболее отвратный код во всей индустрии в силу малого жизненного цикла игр. Я не знаю правда ли это, но причина звучит вполне разумна.
К тому же место работы человека не говорит ни о его способностях ни о качестве его кода, к сожалению.
В gamedev по разному бывает. Где-то весь проект — гадость, где-то все хорошо.
Там я просто указал, на авторитет юбисофта, который без буста.
Я понял, просто Ubisoft можно считать авторитетом в издательстве игр(спорно), но вот в качестве качества кода(а следовательно и его корректности) Ubisoft, для меня, не больший авторитет чем любая другая компания чей софт периодически дает сбои.
Любой софт дает сбои, чей-то больше, чей-то меньше. Ubisoft на этом фоне никаким качественным образом не выделяется.
QNetworkAccessManager — мусор, ну я так думаю по меньшей мере. Еще там есть кучи платформо-зависимых методотов и классов. Ну еще всякого мелкого… Но все-же позитива в нем намного больше и с каждим разом все больше и больше.
Мне кажется такой стиль противоречит стандартному стилю C++ (я про названия классов и переменных с большой буквы). И если в таком коде использовать что-то из stl или boost или из стандартной библиотеки С — то все будет выглядеть очень криво. Не понимаю, что заставило создателей писать библиотеку в таком стиле.
Стандартная библиотека просто унаследовала C-style, который является UNIX-style. Буст пошел по тому же пути. Далеко не всем нравится такой стиль, и мы можем видеть это на примере таких известных C API как: WinAPI, Xlib, Carbon. Все они используют camel в именовании, с начальной заглавное буквой. Более того, если посмотреть на индустрию в целом(C#, Java и т.д.), то можно заметить, что «ООП» языке имеют склонность именно к camel, чем к C-style. С++ хочет быть ближе к ООП, чем к своему прародителю С. Именно поэтому очень многие библиотеки используют camel-style, что, лично я считаю, правильным вектором.
Смущают постулаты 4 (в части расположения фигурной скобке на той же строке с if-ом) и 6…
Лично я считаю, что case должны иметь отступ относительно switch, ибо являются его частью, а не отдельной равной структурой.
case это всего лишь метки (labels). сам по себе блок switch сквозной внутри.
Они метки ВНУТРИ switch-а. Я и метки для goto ставлю так, чтоб он был на уровне кода, обычно обрамляю только пустыми строками сверху и снизу. Правда уже и не помню, когда в последний раз использовал goto… Да и то ассемблер помом был.
Но так получается, что рабочий код внутри switch'а на две позиции смещён. Что не логично.
Код внутри обычного блока, вне зависимости от меток, смещается на один уровень. А тут на 2. Где же логика?
Просто в switch-ах, я метки за метки не считаю. Это как подблоки для меня.
Если речь о необходимости комментариев //fall through, то логично предположить, что разбирая чужой switch ты не можешь знать, забыли здесь break или return, или так задумано.
Это тот же принцип, по которому все кейсы выхода из функции должны быть с return (если функция не возвращает void, конечно).
Вообще-то, приведённые примеры «правильно» расходятся с тем что помечено как «correct» в упомянутой статье. В частности, это касается пробелов между ключевыми словами if, while перед скобкой с условием.
UFO landed and left these words here
zedalert, можете пожалуйста показать, где в моей статье используются слитные скобки? Я наверное очень невнимательный, и не заметил ошибку.
UFO landed and left these words here
Приношу свои извинения, я сначала не понял о чем речь. Спасибо. fixed.
UFO landed and left these words here
Что меня всегда смущало во многих стандартах, так это правила именования констант, енумов и элементов енумов. Например, здесь это вообще не регламентировано.
В Qt принято использовать отступы по 4 пробела. Но именно 4, и именно пробела.

Нет. Нееет!
Любая IDE настраивается на вставку необходимого вам количества пробелов при вставке символа табуляции. Равно как и настраивается ширина отображаемого отступа (в пробелах) при использовании символов табуляции (тут вот неясно, чем табы не угодили — каждый настраивает себе как удобно).
каждый настраивает себе как удобно

DizelGenerator, простите меня, но когда существует проект/фреймворк на десятки тысяч строк кода, лучше чтобы все было одинаково, нежели «как кому удобно». Так что я считаю этот постулат вполне логичным и очень даже правильным.

Представьте ситуацию. Вы участник большого проекта на Qt. Работают над ним 15 человек. И каждый выравнивает «как кому удобно». Вы понимаете что произойдет с кодом?

P.S. А вставлять «хабралинк на хабрачеловека» очень удобно — можно сразу призвать человека в тред и ждать ответа. Всем советую на ответы вставлять его.
Нет-нет, я только за стандарты кодирования! Не раз приходилось поддерживать чужой код, и пол беды, если бы там были свои, отличные от принятых, стандарты, но использовались везде, так обычно и этого нет. Я о том, что если отступы задаются символами табуляции (а не четырьмя пробелами), то кто-то хочет видеть большие отступы и настраивает свой редактор на отображение символа табуляции как 8 пробелов, другой — 4, может быть, 2. Но в коде-то отступы остаются символами табуляции.
Да. Дааааа! ;) На самом деле почему пробелы вполне понятно — борьба с выравниваниями — отступы табами, а выравнивание пробелами. Иногда это бывает пропущено и всё оформление летит. Чтобы не бороться с этим проще постулировать 4 пробела.
Проще…
Вот я не могу понять этого. Серьёзные мужи создают новые языки, пишут кроссплатформенный код, распараллеливают этот код. А запомнить, что отступы табами, а выравнивание пробелами — никак, лучше вообще табы запретить.
Вот именно. Голова занята полезными делами. Зачем отвлекаться на всякие мелочи? Код пишут не только профи, но и новички. И я чаще вижу, что с табами получается жуткая смесь. А с пробелами изначально этой проблемы нет. Минус только в том, что отступ зафиксирован — 4 пробела.
этот вопрос больше религиозный, вым — «Нееет», а мне — «Да»
Я как-то естественным путем пришел к такому же стилю написания кода и считаю его очень наглядным. Так что полностью поддерживаю Qt Coding Style, тем более учитывая, что Qt Framework — основной для меня
У меня та же самая ситуация. Правдо немного со звездочкой мучался в начале. Я писал ее раздельно и от имени переменной, и от типа.
// Я делал так
MyClass * obj = new MyClass( this );

// А надо так
MyClass *obj = new MyClass(this);
UFO landed and left these words here
Постулат №3. Почему * или & должны липнуть к имени переменной?
Постулат №4. Всегда считал что лучше ставить {} в любом случае, даже если одна строка после if или for. Помогает избежать ошибок при добавлении еще одной строки…
Опять-же. Когда есть большой проект, лучше чтобы все было одинаково. Представьте, что 15 человек в проекте, и все пишут по-разному. Это — каша. Гораздо лучше когда есть единый стиль.

А насчет {}, я с вами не согласен. Писать в любом случае — занимает в итоге много места.
То пробел есть то нет… это не хорошо…

// Правильно
if(foo) {
}

// Правильно
if (longExpression
+ otherLongExpression
+ otherOtherLongExpression) {
}

тоже самое с циклами

// Правильно

for (int i = 0; i < 10; ++i)
qDebug("%i", i);

// Правильно
while(a) {}

Смотрится неряшливо. Попробуйте настроить indent под ваши правила и тогда кода всегда будет смотрется однотипно, а не как сейчас…

Извините не удержался. :)
а… это просто автор-переводкик накосопорил с пробелами…

ээх… namespace как же так ведь тэг «Совершенный код» кагбы говорит нам…
Я пробежался поиском "){" и вручную просмотрел — вроде ошибок нету, пробелы стоят везде. Да и вы вставили примеры с пробелами. Можете указать на ошибку?
пробеги поиcком по по «if( » а потом поиском по «if(» в оригинале и ты наконец поймешь, о чем тебе все говорят ибо в оригинале таки «if (» а ты на этот пробел забил.
Чего минусуем-с? Мне неясно просто зачем вообще ставить пробел после if-а и перед скобками с условиями.
Вы когда просто предложение пишете на русском языке, перед скобками тоже пробел не ставите?
Когда я пишу на русском языке, я не использую фигурные скобки. Плохая аналогия.
причем ту фигурные скобки? Речь идет о круглых после «if»
Я также как (судя по всему) как и Evengard подумал что речь идет о "){" а не о «if(». Теперь все понятно, я исправил ошибки.
Нет, я подумал именно про «if(»
Мне непонятно, зачем тут нужен пробел. Когда я пишу функцию, я же не пишу
print («smth»);
Я пишу
print(«smth»);
А всё потому, что аргумент относится к функции. Так же и с if-ом. Условие относится к if-у.
Приношу свои извинения, что-то до меня туго доходит… Сейчас поправлю.
Не согласен со следующими двумя пунктами:

> Для указателей и ссылок, всегда используйте один пробел между типом и ‘*’ или ‘&’, но никогда не ставьте пробел между ‘*’ или ‘&’ и названием переменной

Не согласен, поскольку * и & указывают на тип переменной, а не на имя.

> В этом постулате все предельно просто — главное не писать `virtual` перед названием переопределяемого метода в .h файле.

Категорически не согласен. Главное — ПИСАТЬ virtual! Жаль, что C++ не требует такого написания, как например Object Pascal.
Ну раз уж так, то надо самому хотя бы для себя писать virtual, чтобы всегда помнить, что это не твоя функция, а спущенная тебе сверху по иерархии классов.

UFO landed and left these words here
1. Я тоже привык писать «type& var»/«type* var». Да и в том же стандарте встречаются обе формы записи. Но тем не менее, для большинства coding styles принят именно такой вариант.
2. Тут, скорее всего, как раз целью и было выделить новые виртуальные методы, которые есть в классе. А переопределённые можно пометить override по новому стандарту. (для старого можно просто define сделать, хотя это не будет так же полезно как в c++11)
if (address.isEmpty()) {
return false;
}

Вот так как-раз правильно. Скобки ставить нужно всегда.

Неправильно будет, когда у вас под if (в данном случае) появится какой-то макрос, а скобок нет.
«Карниган & Ричи стайл»(с) — зло! :-)
Закрывающая скобка должна располагаться точно под открывающей. Открывающая скобка в конце строчки чревата своей незаметностью. Даешь каждой фигурной скобке отдельную строчку!

С основным тезисом («Скобки ставить нужно всегда») полностью согласен.
Заведите уже себе нормальную IDE/Редактор с подсветкой блоков, скобок, виртуальных методов и тому подобного, люди 21 век на дворе, хватит кодить в блокноте.
Даже IDE не сможет сделать из вашего кода конфетку, если код написан кое-как. Аккуратность в кодировании повышает читабельность независимо от того, в IDE-ли или в блокноте.
а никто не говорит про кое-как, речь идет про избыточность. Излишняя избыточность только затрудняет понимание кода. Приведу пример:
Многие против постулата №8 и мотивируют это тем что virtual позволяет им отличать методы спущенные сверху от своих, но они например при таком подходе не смогут отличить собственные методы virtual (которые никуда не спущены) от методов спущенных сверху, однако —
Используя постулат №8 и современную IDE (например Qt Creator) мы может отличить мы сможет отличить спущенные сверху переопределенные виртуальные метода (слова virtual нет, имя метода написано курсивом), от собственных виртуальных методов (слово virtual есть, имя метода написано курсивом) и от обычных методов тоже (слова virtual нет, имя метода написано нормальным шрифтом)

Вообщем не надо искать удобства там где их нет.
Значит макрос неверный. Любой макрос, который состоит не из одного оператора надо заключать в do {… } while(0)
Only those users with full accounts are able to leave comments. Log in, please.