Жанр: Учеба

сторінка №1

Правила программирования на Си и Си плюс плюс.



ВЕРЕВКА
ДОСТАТОЧНОЙ ДЛИНЫ,
ЧТОБЫ! ВЫСТРЕЛИТЬ
СЕБЕ В НОГУ

Правила программирования на Си и Си++

Ален И. Голуб

Москва 2001


Программисты, инженеры, научные работники, студенты и все, кто
работает с Си или Си++! Если вы хотите писать лучший код без
блужданий по лабиринтам технической документации, то это краткое, но
содержательное руководство является именно тем, что вам нужно.
"Веревка достаточной длины, чтобы! выстрелить себе в ногу"
предлагает более 100 практических правил, которые вы сможете
использовать для создания элегантного, простого в сопровождении кода.
А так как книга написана признанным знатоком в этой области, то и вы в
ней не заблудитесь.
Ален Голуб предлагает необходимый набор пояснений, советов и
технических приемов с целью помочь вам полностью использовать
возможности этих чрезвычайно мощных языков. Но не бойтесь встретить
очередное скучное руководство по программированию. Автору удается
сделать изложение столь серьезной темы живым и интересным за счет
рассыпанного по тексту юмора и глубокого знания предмета.
Голуб рассматривает универсальные правила, форматирование и
правильную организацию программ перед тем, как углубиться в такие
основополагающие вопросы, как:
Практические способы организации и написания сопровождаемого
кода.
Объектно-ориентированное программирование и методы
абстракции данных.
Как избежать проблем, специфических для Си и Си++.
Для закрепления правил, намеченных в этой книге в общих чертах,
предлагается множество примеров. Вы также найдете здесь полезные
проектные стратегии, освещение вопросов административного
управления и многое другое.

Original copyright. McGraw-Hill, 1995
Перевод с английского языка. В.Зацепин, 1996
Редакция и текст примечаний. В.Базаров, 1998
Оформление Интернет-версии. В.Зацепин, 2001


Посвящается Аманде 27. Комментарий должен предоставлять только нужную для сопровождения
информацию ............................................................................................................40
29. Комментарии должны быть выровнены вертикально..........................................42
30. Используйте аккуратные столбцы везде, где можно............................................44
31. Не располагайте комментариев между именем функции и открывающей
скобкой ....................................................................................................................45
32. Помечайте конец длинного составного оператора чем-нибудь, имеющим
смысл .......................................................................................................................45
33. Располагайте в строке только один оператор .......................................................46
34. Указывайте имена аргументов в прототипах функций ........................................47
35. Используйте "предикатную" форму при разбиении длинных выражений.........47
36. Подпрограмма должна помещаться на экране .....................................................48
37. Нужно обеспечивать возможность распечатки всего текста программы...........48
38. Используйте штриховую линию для зрительного разделения подпрограмм ....49
39. Пробел - один из наиболее эффективных комментариев..................................50
40. Используйте отступы в четыре пробела................................................................51
41. Условные операторы выделяются абзацными отступами ...................................52
41.1. Комментарии должны иметь тот же отступ, что и окружающий текст
программы ...............................................................................................................53
42. Выравнивайте скобки вертикально по левой границе .........................................54
43. Используйте скобки, если в условном операторе имеется более, чем одна
строка .......................................................................................................................54

Часть 4. ИМЕНА И ИДЕНТИФИКАТОРЫ................................................................56


44. Имена должны быть обычными словами английского языка, описывающими
то, что делает функция, аргумент или переменная ..............................................57
44.1. Не используйте в качестве имен тарабарщину ...................................................58
45. Имена макросов должны записываться ЗАГЛАВНЫМИ_БУКВАМИ ..............59
45.1. Не используйте заглавных букв для констант перечисления ............................59
45.2. Не используйте заглавных букв в именах типов, созданных при помощи
typedef .................................................................................................................59
46. Не пользуйтесь именами из стандарта ANSI Cи ..................................................60
47. Не пользуйтесь именами Microsoft........................................................................60
48. Избегайте ненужных идентификаторов ................................................................62
49. Именованные константы для булевых величин редко необходимы...................62

Часть 5. ПРАВИЛА ОБЫЧНОГО ПРОГРАММИРОВАНИЯ ................................66


50. Не путайте привычность с читаемостью...............................................................67
51. Функция должна делать только одно дело............................................................69
52. Иметь слишком много уровней абстракции или инкапсуляции так же плохо,
как и слишком мало ................................................................................................69
53. Функция должна вызываться более одного раза, но! ........................................70
53.1. Код, используемый более одного раза, должен быть помещен в функцию.....71
54. Функция должна иметь лишь одну точку выхода ................................................71
54.1. Всегда предусматривайте возврат значения из блока внешнего уровня..........72
55. Избегайте дублирования усилий............................................................................73
56. Не захламляйте область глобальных имен............................................................74
56.1. Избегайте глобальных идентификаторов............................................................74


Правила программирования на Си и Си++

6


56.2. Никогда не требуйте инициализации глобальной переменной при вызове
функции ................................................................................................................... 75
56.2.1. Делайте локальные переменные статическими в рекурсивных функциях,
если их значения не участвуют в рекурсивном вызове ....................................... 76
56.3. Используйте счетчик экземпляров объектов вместо инициализирующих
функций ................................................................................................................... 77
56.4. Если оператор if завершается оператором return, то не используйте
else ........................................................................................................................ 78
57. Помещайте более короткий блок условного оператора if/else первым....... 80
58. Старайтесь сдвинуть ошибки с этапа выполнения на этап компиляции............ 80
59. Применяйте указатели на функции Си в качестве селекторов ........................... 81
60. Избегайте циклов do/while ................................................................................ 83
60.1. Никогда не используйте do/while для бесконечного цикла.......................... 84
61. В цикле со счетчиком его значение должно по возможности уменьшаться ..... 84
62. Не делайте одно и то же двумя способами одновременно.................................. 84
63. Используйте оператор for, если имеются любые два из инициализурующего,
условного или инкрементирующего выражений ................................................. 85
64. То, чего нет в условном выражении, не должно появляться и в других частях
оператора for......................................................................................................... 87
65. Допускайте, что ситуация может измениться в худшую сторону ...................... 87
66. Компьютеры не знают математики ....................................................................... 88
66.1. Рассчитывайте на невозможное........................................................................... 89
66.2. Всегда проверяйте коды возврата ошибки ......................................................... 90
67. Избегайте явно временных переменных............................................................... 90
68. Не нужно магических чисел................................................................................... 91
69. Не делайте предположений о размерах ................................................................ 91
70. Опасайтесь приведения типов (спорные вопросы Си) ........................................ 93
71. Немедленно обрабатывайте особые случаи ......................................................... 95
72. Не старайтесь порадовать lint ................................................................................ 97
73. Помещайте код, динамически распределяющий и освобождающий память,
в одном и том же месте .......................................................................................... 98
74. Динамическая память - дорогое удовольствие .................................................. 99
75. Тестовые подпрограммы не должны быть интерактивными............................ 100
76. Сообщение об ошибке должно подсказывать пользователю, как ее
исправить............................................................................................................... 101
77. Не выводите сообщения об ошибке, если она исправима................................. 102
78. Не используйте системно-зависимых функций для сообщений об ошибках .. 102

Часть 6. ПРЕПРОЦЕССОР ......................................................................................... 104


79. Все из одного .h файла должно быть использовано в, по меньшей мере,
двух .c файлах ..................................................................................................... 105
80. Используйте вложенные директивы #include .............................................. 105
81. Вы должны быть всегда способны заменить макрос функцией ....................... 106
81.1. Операция ?: не то же самое, что и оператор if/else ................................. 111
81.2. Помещайте тело макроса и его аргументы в круглые скобки......................... 112
82. enum и const лучше, чем макрос...................................................................... 11383. Аргумент параметризированного макроса не должен появляться в правой
части более одного раза........................................................................................114
83.1. Никогда не используйте макросы для символьных констант .........................115
84. Если все альтернативы отпали, то используйте препроцессор .........................116

Часть 7 . ПРАВИЛА, ОТНОСЯЩИЕСЯ К ЯЗЫКУ СИ.........................................119


85. Подавляйте демонов сложности (часть 2)...........................................................120
85.1. Устраняйте беспорядок.......................................................................................120
85.2. Избегайте битовых масок; используйте битовые поля ....................................121
85.3. Не используйте флагов завершения...................................................................123
85.4. Рассчитывайте, что ваш читатель знает Си ......................................................124
85.5. Не делайте вид, что Си поддерживает булевый тип (#define TRUE ) ..124
86. Для битового поля размером 1 бит должен быть определен тип unsigned..126
87. Указатели должны указывать на адрес, больший, чем базовый для массива ..126
88. Используйте указатели вместо индексов массива..............................................127
89. Избегайте goto, за исключением!....................................................................128

Часть 8. ПРАВИЛА ПРОГРАММИРОВАНИЯ НА СИ++ .....................................132


Часть 8а. ВОПРОСЫ ПРОЕКТИРОВАНИЯ И РЕАЛИЗАЦИИ ..........................133


90. Не смешивайте объектно-ориентированное и "структурное"
проектирование .....................................................................................................133
90.1. Если проект не ориетирован на объекты, то используйте Си .........................133
91. Рассчитывайте потратить больше времени на проектирование и меньше на
разработку..............................................................................................................135
92. Библиотеки классов Си++ обычно не могут быть использованы
неискушенными пользователями ........................................................................136
93. Пользуйтесь контрольными таблицами ..............................................................137
94. Сообщения должны выражать возможности, а не запрашивать
информацию ..........................................................................................................139
95. Вам обычно не удастся переделать имеющуюся структурную программу в
объектно-ориентированную.................................................................................139
96. Объект производного класса является объектом базового класса....................141
97. Наследование - это процесс добавления полей данных и методов-членов ...141
98. Сначала проектируйте объекты ...........................................................................144
99. Затем проектируйте иерархию снизу вверх ........................................................144
99.1. Базовые классы должны иметь более одного производного объекта.............145
100. Возможности, определенные в базовом классе, должны использоваться
всеми производными классами............................................................................145
101. Си++ - это не Smalltalk: избегайте общего класса object...........................145
102. Смешения не должны наследоваться от чего попало .......................................151
103. Смешения должны быть виртуальными базовыми классами...........................151
104. Инициализируйте виртуальные базовые классы при помощи конструктора,
используемого по умолчанию..............................................................................151
105. Наследование не подходит, если вы никогда не посылаете сообщения
базового класса объекту производного класса...................................................152
106. Везде, где можно, предпочитайте включение наследованию ..........................152
107. Используйте закрытые базовые классы лишь когда вы должны обеспечить
виртуальные замещения .......................................................................................152


Правила программирования на Си и Си++

8


108. Проектируйте структуры данных в последнюю очередь ................................. 153
109. Все данные в определении класса должны быть закрытыми........................... 154
110. Никогда не допускайте открытого доступа к закрытым данным .................... 154
110.1. Не пользуйтесь функциями типа get/set (чтения и присваивания
значений) ............................................................................................................... 158
111. Откажитесь от выражений языка Си, когда программируете на Си++........... 160
112. Проектируйте с учетом наследования................................................................ 161
112.1. Функция-член должна обычно использовать закрытые поля данных
класса..................................................................................................................... 162
113. Используйте константы....................................................................................... 163
114. Используйте структуры только тогда, когда все данные открытые и нет
функций-членов .................................................................................................... 164
115. Не размещайте тела функций в определениях классов .................................... 165
116. Избегайте перегрузки функций и аргументов, используемых по умолчанию 169

Часть 8б. ПРОБЛЕМЫ СЦЕПЛЕНИЯ ..................................................................... 171


117. Избегайте дружественных классов..................................................................... 171
118. Наследование - это форма сцепления.............................................................. 172
119. Не портьте область глобальных имен: проблемы Си++................................... 173

Часть 8в. ССЫЛКИ....................................................................................................... 177


120. Ссылочные аргументы всегда должны быть константами............................... 177
121. Никогда не используйте ссылки в качестве результатов, пользуйтесь
указателями ........................................................................................................... 177
122. Не возвращайте ссылки (или указатели) на локальные переменные .............. 181
123. Не возвращайте ссылки на память, выделенную оператором new ................. 181

Часть 8г. КОНСТРУКТОРЫ, ДЕСТРУКТОРЫ И OPERATOR=( ).................... 183


124. Операция operator=( ) должна возвращать ссылку на константу ........... 184
125. Присваивание самому себе должно работать.................................................... 184
126. Классы, имеющие члены-указатели, должны всегда определять
конструктор копии и функцию operator=()................................................. 185
127. Если у вас есть доступ к объекту, то он должен быть инициализирован........ 186
128. Используйте списки инициализации членов ..................................................... 186
129. Исходите из того, что члены и базовые классы инициализируются
в случайном порядке ............................................................................................ 186
130. Конструкторы копий должны использовать списки инициализации членов . 188
131. Производные классы должны обычно определять конструктор копии и
функцию operator=( ) ............................................................................................ 189
132. Конструкторы, не предназначенные для преобразования типов, должны
иметь два или более аргумента ........................................................................... 192
133. Используйте счетчики экземпляров объектов для инициализации
на уровне класса ................................................................................................... 193
134. Избегайте инициализации в два приема ............................................................ 194
135. Суперобложки на Си++ для существующих интерфейсов редко хорошо
работают................................................................................................................ 194

Часть 8д. ВИРТУАЛЬНЫЕ ФУНКЦИИ................................................................... 198


136. Виртуальные функции - это те функции, которые вы не можете
написать на уровне базового класса ................................................................... 198137. Виртуальная функция не является виртуальной, если вызывается из
конструктора или деструктора.............................................................................199
138. Не вызывайте чисто виртуальные функции из конструкторов ........................203
139. Деструкторы всегда должны быть виртуальными ............................................203
140. Функции базового класса, имеющие то же имя, что и функции
производного класса, обычно должны быть виртуальными .............................204
141. Не делайте функцию виртуальной, если вы не желаете, чтобы
производный класс получил контроль над ней ..................................................205
142. Защищенные функции обычно должны быть виртуальными ..........................205
143. Опасайтесь приведения типов (спорные вопросы Си++) .................................206
144. Не вызывайте конструкторов из операции operator=( )...........................208

Часть 8е. ПЕРЕГРУЗКА ОПЕРАЦИЙ .......................................................................211


145. Операция - это сокращение (без сюрпризов) ..................................................211
146. Используйте перегрузку операций только для определения операций,
имеющих аналог в Си (без сюрпризов)...............................................................212
147. Перегрузив одну операцию, вы должны перегрузить все сходные с ней
операции ................................................................................................................213
148. Перегруженные операции должны работать точно так же, как они
работают в Си........................................................................................................214
149. Перегруженной бинарной операции лучше всего быть встроенным (inline)
псевдонимом операции приведения типа ...........................................................215
150. Не теряйте разум с операторами преобразования типов ..................................217
151. Если можно, то делайте все преобразования типов с помощью
конструкторов .......................................................................................................217

Часть 8ж. УПРАВЛЕНИЕ ПАМЯТЬЮ .....................................................................219


152. Используйте new/delete вместо malloc()/free()................................219
153. Вся память, выделенная в конструкторе, должна быть освобождена в
деструкторе............................................................................................................219
154. Локальные перегрузки операторов new и delete опасны .............................219

Часть 8з. ШАБЛОНЫ ...................................................................................................220


155. Используйте встроенные шаблоны функций вместо параметризированных
макросов ................................................................................................................220
156. Всегда знайте размер шаблона после его расширения .....................................221
157. Шаблоны классов должны обычно определять производные классы.............224
158. Шаблоны не заменяют наследование; они его автоматизируют......................224

Часть 8и. ИСКЛЮЧЕНИЯ...........................................................................................228


159. Назначение исключений - не быть пойманными ............................................228
160. По возможности возбуждайте объекты типа error ........................................231
161. Возбуждение исключений из конструктора ненадежно ...................................233
ЗАКЛЮЧЕНИЕ..............................................................................................................240
ОБ АВТОРЕ ....................................................................................................................241



Благодарности

Работа над этой книгой затянулась, и я весьма обязан трем редакторам
издательства McGraw-Hill, которые по очереди мирились с постоянными
задержками с моей стороны: Нэйлу Ливайну, Дэну Гонно и Дженифер
Холт-Диджованна. Я особенно признателен Бобу Дюшарму, который
защитил меня от самого себя, сделав очень тщательный просмотр
первоначального наброска. Его советы значительно улучшили книгу в ее
нынешнем виде.



Введение

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

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

Список сторінок

Поділитися у соцмережах

☏ Замовлення реклами: +3805044-68-872

© Асоціація електронних бібліотек України

☝ Усі матеріали сайту (зокрема статті, зображення, рекламні оголошення тощо) призначені лише для попереднього ознайомлення. Усі права на публікації, представлені на сайті, належать їхнім законним власникам. Просимо Вас не зберігати копії інформації.