Недостаточно хорошо оставить в покое, а вместо этого использовать C.
Что ж, плохой дизайн программы выходит за рамки языков (приведение типов, игнорирование предупреждений, ненужная магия прекомпилятора, ненужная перестановка битов, неиспользование макросов классификации символов) и Сам язык C не порождает слишком много «вредных привычек» (хорошо, макросы, особенно из каменного века), и многие идиомы переводятся напрямую. Но некоторые из них могут быть рассмотрены:
Использование функции только потому, что она написана на C ++ и, следовательно, это должен быть правильный способ что-то сделать. Некоторым программам просто не нужны наследование, MI, исключения, RTTI, шаблоны (как бы они ни были хороши ... нагрузка отладки велика) или вещи виртуальных классов.
Придерживаемся фрагмента кода из C, не думая, есть ли у C ++ лучший способ. (Есть причина, по которой у вас теперь есть class, private, public, const (расширенный за пределы C89), функции статического класса, ссылки.
Незнание библиотеки ввода-вывода C ++ (ее БОЛЬШАЯ, и вам нужно знать это ) и смешивание ввода-вывода C ++ и ввода-вывода C.
Он думает, что C ++ - это просто немного другой язык, отличный от C. Он продолжит программировать C, замаскированный C ++. Никакого расширенного использования классов, структуры считаются менее мощными, чем классы, пространство имен, новые заголовки, шаблоны, ничего из этих новых элементов не используется. Он продолжит объявлять целочисленные вары без int, не будет предоставлять прототипы функций. Он будет использовать malloc и бесплатные небезопасные указатели и препроцессор для определения встроенных функций. Это лишь небольшой список;)
Мне больше всего нравится программист на C, который пишет один метод с несколькими необязательными аргументами.
По сути, функция будет делать разные вещи в зависимости от значений и / или допустимости пустых значений аргументов.
Сделать все в классе общедоступным. Итак, члены данных, которые должны быть приватными, не являются.
Запись с использованием пространства имен std
, потому что все это делают, а затем никогда не отражают по его значению.
Или зная, что это значит, но фраза « std :: cout <<" Hello World "<< std :: endl;
выглядит некрасиво».
Использование приведений в стиле C.
C ++ позволяет независимо выбирать, разрешать ли приведение типов между несвязанными типами и разрешать ли изменения в квалификаторах const
и volatile
, что значительно улучшает безопасность типов во время компиляции по сравнению с с C. Он также предлагает полностью безопасное приведение за счет проверки во время выполнения.
Приведения типов в стиле C, неконтролируемые преобразования между практически любыми типами, допускают наличие целых классов ошибок, которые можно легко идентифицировать с помощью более строгих приведений. Их синтаксис также затрудняет их поиск, если вы хотите проверить ошибочный код на предмет сомнительных преобразований.
Одно слово: макросы. Я не говорю, что макросам вообще нет места в C ++, но бывшие программисты на C, как правило, слишком часто их используют после перехода на C ++.
Очень опытные разработчики, не понимающие кастинг или даже объектно-ориентированное программирование:
Я начал помогать в проекте, и у одного из старших ребят возникла проблема с некоторым кодом, который раньше работал и сейчас нет.
(Имена классов были изменены, чтобы защитить невиновных, и я не могу вспомнить точные имена) У него был код на C ++, который прослушивал классы входящих сообщений и читал их.Раньше это работало так, что ему передавался класс Message, и он вставлял в него переменную, чтобы узнать, что это за тип сообщения. Затем он в стиле C преобразовал Message в другой специализированный класс, который он написал, унаследованный от Message. В этом новом классе были функции, которые извлекали данные так, как он этого хотел. Теперь это работало для него нормально, но теперь нет.
После многих часов просмотра кода он не увидел проблемы, и я посмотрел через его плечо. Я сразу сказал ему, что преобразовывать сообщение в стиле C в производный класс - не лучшая идея, а это не так. Он не согласился со мной и сказал, что делал это годами, и если это было неправильно, то все, что он делает, неправильно, потому что он часто использует этот подход. Кроме того, его поддержал подрядчик, который сказал мне, что я был неправ. Они оба утверждали, что это всегда работает, и код не изменился, так что не этот подход, а что-то еще нарушило его код.
Я посмотрел немного дальше и обнаружил разницу. Последняя версия класса Message имела виртуальную функцию и ранее не использовала virtual. Я сказал им обоим, что теперь существует виртуальная таблица, функции просматриваются и т.д. и т.п. комментарий, который я никогда не забуду: «Виртуал полностью портит полиморфизм и объектно-ориентированное программирование».
Я отправил им копию шаблона декоратора в качестве примера того, как добавить функцию к существующему классу, но ничего не получил от них.Как они закрепили идею, я понятия не имею.
Добавление с использованием
в файлы заголовков, чтобы они могли избегать имен вроде std :: string
в объявлениях типов.
Отсутствие использования STL, особенно std :: string,
и / или
, использование std :: strings и возврат к старым строковым функциям c в труднодоступных местах.
Объявление всех переменных в верхней части функции, а не как можно ближе к тому месту, где они используются.
Передача объектов с указателями вместо ссылок. Да, бывают случаи, когда вам нужны указатели в C ++, но ссылки более безопасны, поэтому вам следует использовать их, когда это возможно.
Объявление всех переменных в начале самой функции, даже если переменная будет использоваться только после 100 строк или около того.
Особенно часто случается с локальными переменными, объявленными внутри функции.
Использование необработанных указателей и ресурсов вместо объектов RAII.
Непонятное использование структур по сравнению с классами, чрезмерное использование глобальных методов, которые принимают указатели объектов в качестве аргументов и глобально доступных указателей экземпляров, а-ля:
extern Application* g_pApp;
void RunApplication(Application* app, int flags);
Также (не говоря уже о том, что это совершенно бесполезно, но все же):
const void* buf;
Неполное понимание семантики указателей и ссылок и того, когда использовать тот или иной. С указателями также связана проблема неправильного управления динамически выделяемой памятью или невозможности использовать для этого «умные» конструкции (например, интеллектуальные указатели).
Предположим, что указанные программисты уже совершили ошибку, пытаясь изучить C ++:
Решение проблемы вместо создания классового чудовища, гарантирующего вам медицинскую страховку и 401 тысячу льгот.
Реализация lisp в одном файле и проектирование в нем.
Написание обычных читаемых функций вместо замещающих операторов?
Написание в стиле, понятном младшим программистам, которые считают хорошей практикой «не писать на C ++».
Обращение к ОС на ее собственном языке.
Не использовать шаблоны при создании алгоритмов и структур данных (пример). Это делает вещи либо слишком локализованными, либо слишком общими
Например, писать
void qsort(MyStruct *begin, size_t length); //too localized
void qsort(void *begin, size_t length,
size_t rec_size, int(compare*)(void*,void*)); //too generic
вместо
template <class RA_Iter>
void qsort(RA_Iter begin, size_t length);
//uses RA_Iter::value_type::operator< for comparison