C: Хорошие привычки: переход на C ++ - PullRequest
19 голосов
/ 14 сентября 2009

Я изучаю C в Varsity всего 2 месяца, и в следующем году мы перейдем к C ++.

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

Когда вы изучили C, а затем C ++, изменился ли способ, которым вы кодировали в C, каким-либо образом?

Ответы [ 13 ]

27 голосов
/ 14 сентября 2009

Хороших ответов уже много. Мой будет более "ориентированным на мышление".

Данные против действий!

  • В C все делается, чтобы думать как «Применить этот эффект к этим данным».
  • В C ++ это больше похоже на «Данные должны вести себя».

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

Я нашел эту идею "Данные должны вести себя" очень хорошим руководящим принципом при кодировании на C ++.

C ++ синтаксический сахар не является обязательным

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

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

Руководящие принципы, такие как «Я могу сделать это по-С», просто заставят вас пропустить вагон. Лучше вообще не начинать изучать C ++, если у вас уже есть этот тип C-центрического мышления.

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

C-совместимый код C ++ - это семантическая ошибка

Тип-определение ваших структур для их компиляции компилятором C - плохая шутка. Использование указателей вместо ссылок - это пощечина вашему будущему я. extern "C" только сделает ваш код слабее, а не сильнее. А использование void * для универсальности только увеличит количество коллег-программистов на C ++, которые с радостью заплатят за то, что ваша голова будет удалена невероятно болезненным способом.

Никогда не пытайтесь писать C-совместимый код, если вам действительно не нужно действительно .

Вы просто утяжелите себя трудоемким стилем кодирования для функции, которую вы никогда не будете использовать.

Компилятор - сильный друг / враг

Работа на низком уровне странно влияет на некоторых разработчиков. Они очень верят в свой контроль над скомпилированным кодом. Делегировать этот контроль конструкциям более высокого уровня трудно для них.

Хорошим примером этого является отказ от шаблона конструктора / деструктора, потому что " иногда конструкторам отнимает слишком много времени ... Лучше сделать это по-моему ... ".

Компилятор C ++ вполне способен оптимизировать явно неоптимизированный код. На самом деле код, созданный компилятором, может сильно отличаться от того, который, как вы считаете, вы создали.

Не пытайтесь быть лучше / умнее компилятора, потому что:

  1. Вы, вероятно, уже проиграли, так как даже старые компиляторы обычно будут генерировать лучший код, чем вы можете мечтать сделать сегодня
  2. Даже если вы выиграли бой сегодня, он автоматически превратится в поражение завтра, так как компиляторы будут становиться все лучше и лучше в будущем, поэтому ваш «оптимизированный код» сегодня станет узким местом программы и предметом рефакторинга. последующие годы (не говоря уже о позорных воспоминаниях для вас).

Итак, доверьтесь своему компилятору.

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

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

Знайте преимущества / недостатки / затраты каждой конструкции C ++

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

Невежество не освобождает от ответственности.

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

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

Будь скромным

Есть люди, проводящие исследования в C ++, которые были лучше в C ++ в день своего рождения, чем большинство из нас когда-либо. Даже если мы игнорируем Страуструп , такие имена, как Мейерс , Абрахамс , Александреску , Саттер и т. Д. Регулярно обрезаются наряду с новыми идеями. Несмотря на (или как следствие) свой внешний взгляд, STL - революционная библиотека. А библиотека, подобная Boost , несмотря на ее «небольшой размер» по сравнению с некоторыми законченными средами (например, Java или .NET API), представляет собой массивный репозиторий отличного кода, предлагаемого вам для изучения.

Только потому, что вы нашли какую-то новую функцию "странной" или "чужой", не стоит недооценивать ее. Пытаясь понять это, PERHAPS предоставит вам другой инструмент в вашем распоряжении, и ВСЕГДА увеличит ваше владение языком, и ВСЕГДА заставит ваш мозг работать, что хорошо в бизнесе разработчиков.

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

RAII !!!!

Если ты не знаешь, что это такое, учись.

Без RAII ваш код C ++ является просто ошибочным кодом, который позволяет избежать ошибки компиляции.

RAII является единственным наиболее важным понятием C ++.

Все остальное связано.

19 голосов
/ 14 сентября 2009

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

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

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

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

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

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

C ++ также поддерживает стандартное программирование, которое часто предпочтительнее, чем OOP. Также имеется ограниченная поддержка функционального программирования. И, конечно же, он все еще поддерживает процедурное программирование в стиле C. Хитрость в C ++ состоит в том, чтобы понять все это, чтобы вы знали, когда использовать. Это сила C ++, способность переключаться между этими парадигмами и смешивать их. Люди, которые называют C ++ языком ООП, упускают из виду этот момент так же, как и люди, которые называют его улучшенным языком C. Он позволяет вам писать код в любом из этих стилей, но ни один из них не имеет смысла. C - лучший C-подобный язык, и существует множество лучших языков ООП. Если вы хотите придерживаться одной единственной парадигмы, используйте язык, разработанный для этого.

10 голосов
/ 14 сентября 2009

Забавно, как много людей здесь утверждают, что C и C ++ «совершенно разные», и как «C ++ является объектно-ориентированным, C - нет» ...

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

Во-вторых, не дайте себя обмануть, полагая, что C ++ - это "объектно-ориентированный язык". C ++ - это язык, который поддерживает ориентацию объекта, true. Но он также поддерживает общее программирование и процедурное программирование. Сосредоточение внимания только на аспекте ООП в C ++ отнимает значительную часть его мощности.

Что касается привычек ... не слишком привязывайтесь к строкам в стиле C (char *) и массивам (int foo[]). Оба очень редко используются в C ++, так как есть гораздо более мощные (и удобные) замены, string и vector.

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

При проектировании вашего C-кода начните с struct, содержащего соответствующие данные (например, поля адреса), а затем создайте функции, работающие с этим типом структуры (address_read( struct address_t * ), address_write( struct address_t * ), address_modify_name( struct address_t *, char * ) и т. Д. ). Добавьте функцию main(), которая вызывает эти функции в соответствующем порядке. Данные являются важной частью программы, а не функцией. Это то, что облегчит переход на C ++ (и объектную ориентацию).

Это еще не все, но я не претендую на то, что отвечаю на все в одном посте. : -)

7 голосов
/ 14 сентября 2009

Если вы можете получить его, я бы порекомендовал первые 3 главы Язык программирования C ++ создателем C ++ Бьярном Страуструпом.

В частности, «Примечания для читателя» и «Тур по C ++» дадут вам хорошее понимание того, где и как C ++ отличается от C, и сосредоточат ваше дальнейшее обучение. Конечно, всю книгу полезно иметь рядом при работе с C ++.

Интересно, что в вашей ситуации в главе 1 Бьярне на самом деле говорит:

"в продолжающейся дискуссии о нужно изучать C до C ++, я твердо убежден, что лучше идти непосредственно к C ++ ".

Конечно, будет, не так ли, но если вы примете его аргументацию, вам лучше сразу же перейти к C ++ как можно скорее.

6 голосов
/ 14 сентября 2009

Храните языки отдельно.

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

При переходе на C ++ будьте готовы отучиться (изучите другой несовместимый метод) о:

  1. препроцессор : в C ++ вы не должны использовать препроцессор так часто, как в C.
  2. строки : C не имеет их
  3. указатели : C ++ может быть закодирован для более безопасной обработки
4 голосов
/ 14 сентября 2009

Я предполагаю, что C ++, который вы будете изучать, вероятно, не будет чрезмерно объектно-ориентированным, по крайней мере, так было не в моем университете. Мы запускали программы на C ++ по существу как программы на C.

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

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

Поищите в Интернете учебники по простым программам на C ++ ... CodeProject - это всегда хороший ресурс.

4 голосов
/ 14 сентября 2009

Переход на C ++ означает, что вы почувствовали, что вам нужны классы или лучшие библиотеки. Вот что я чувствую. Я также изучаю лучшие возможности C ++, с моим фоном Си. До сих пор я рассматривал векторы в основном [кроме классов и шаблонов].

Я чувствую, что языки слишком похожи на

думайте о них совершенно отдельно.

4 голосов
/ 14 сентября 2009

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

Например, даже простая программа «Hello World» значительно отличается:

C:

#include <stdio.h>
int main(void)
{
  printf("Hello, world!\n");
  return 0;
}

C ++:

#include <iostream>
int main()
{
   std::cout << "Hello, world!\n";
}

(примеры из здесь ).

Поскольку 'printf' является функцией, тогда как 'cout' является не функцией, а экземпляром класса ostream.

Дальнейшее чтение: iostream .

3 голосов
/ 14 сентября 2009

Максимально используйте структуры и указатели на функции, чтобы имитировать методы классов и абстрактные методы.

Например, если вы хотите определить транспортное средство и автомобиль, полученный из транспортного средства с использованием C, вы должны написать (извините, я не проверю код :-)):

struct Vehicle
  {
  void (*checkFuel)(Vehicle*);
  void (*start)(Vehicle*);
  void (*move)(Vehicle*);
  void (*stop)(Vehicle*);
  }

void start1(Vehicle* v)
  {
  v->checkFuel(v);
  printf("START!");
  }

void start2(Vehicle* v)
  {
  v->checkFuel(v);
  printf("VROOOOMM!");
  }


struct Car
  {
  Vehicule base;
  int (*klaxon)(Car*);
  }

Vehicule* newVehicule()
 {
 Vehicule* v=(Vehicule*)malloc(sizeof(Vehicule));
 v->start= start1;
 v->move=
 (...)
 return v;
 }


Car* newCar()
 {
 Car* c=(Car*)malloc(sizeof(Car));
 Vehicule* v=(Vehicule*)c;
 v->start= start2;
 v->move=
 (...)
 c->kaxon=(...)
 return c;
 }
2 голосов
/ 14 сентября 2009

Вот несколько моментов:

1) Убедитесь, что вы хорошо владеете указателями. Сосредоточьтесь на том, как работают массивы и указатели, в чем их сходство и различия.

2) Лучший способ улучшить c - это писать программы. Напишите как можно больше. Для начала вы можете написать пользовательские функции для некоторых функций библиотеки. Вы можете попробовать свои силы на Strcpy, strcmp, strncpy, memcpy, memmove.

3) Научитесь отлаживать. (Gdb действительно круто).

4) Начните следовать определенному стилю кодирования и попытайтесь придерживаться его.

5) Всегда снабжайте свой код содержательными комментариями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...