Что я могу ожидать, когда я перехожу от C & С# к С++?

Вот простой вопрос.

Я сделал много работы, используя как C, так и С# (2.0), но никогда ничего на С++. Что я могу ожидать при изучении С++? Будут ли какие-либо большие проблемы или препятствия, на которые я должен обратить внимание? Есть ли у кого-нибудь хорошие рекомендации по курсу/веб-сайту для изучения С++ для опытного программиста?

14 ответов

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

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

В С++ многие C-конструкции, хотя и законные, в основном избегают:

  • Необработанные указатели (обычно заменяются интеллектуальными указателями, такими как boost::shared_ptr или std::auto_ptr, или со ссылками
  • Распределение памяти в пользовательском коде (обычно должно быть включено в интеллектуальный указатель или в пользовательский объект RAII)
  • Указатели функций (обычно заменяются функторами, для повышения безопасности и производительности)
  • goto (часто используется в C для перехода на очищающий код. Снова, сделанный ненужным с помощью RAII)
  • препроцессор (практически никогда не нужен. Предпочитают шаблоны вместо этого)

Конечно, есть исключения из каждой из этих точек, но, как правило, код С++, в отличие от кода C, в значительной степени устраняет все их использование.

И больше, чем в С#, классы - это действительно рабочие лошади, делающие много тяжелой работы. В С# класс - это немного больше, чем немного лесов, контейнер, в котором хранятся все ваши методы. Конечно, у него есть конструктор, и он может реализовать Dispose(); но С++ принимает это намного больше, и у вас есть:

  • Конструктор (как и в С#, который инициализирует класс с нуля)
  • Конструктор копирования (инициализирует класс как копию другого объекта)
  • Оператор присваивания (поскольку классы - это то, что С# будет рассматривать типы значений. И поэтому назначение - это не просто изменение ссылки, а копирование по всему содержимому объекта, определяемым пользователем)
  • Деструктор

Деструктор, вероятно, является самым важным понятием в С++. Это жизненно важно для RAII, которым управляют память или другие ресурсы, потому что она автоматически вызывается, когда объект выходит за рамки. Это позволяет вашим классам выполнять множество гарантий, которых невозможно достичь на C или С#. Например, boost:: thread предоставляет блокированные блокировки, которые, как гарантируется, будут выпущены при выходе из области видимости, возвращается ли функция нормально, генерируется исключение или что-то еще. Поэтому при использовании этой библиотеки пользователю не нужно беспокоиться о выпуске блокировок или других ресурсов. Это просто происходит автоматически, как только вы закончите с ними.

В некотором смысле, это дает вам намного больше крючков для настройки поведения вашего класса. В отличие от С#, вы точно контролируете, что происходит, когда выполняется простое назначение. Вы контролируете, что происходит, когда класс выходит из области действия, когда он инициализируется с нуля или как копия другого объекта. Это позволяет правильно писать класс, который будет практически невозможно использовать неправильно. (Почти)

Кроме того, шаблоны и метапрограммирование шаблонов - это концепции, с которыми вы, вероятно, столкнетесь. Они очень мощные инструменты, поэтому убедитесь, что вы с ними дружите.:)


Вот некоторые из моих точек зрения:

  • Указатели играют большую роль в С++. Пока в С# у вас есть только ссылка типы. И вы можете получить головную боль от ошибка указателя.
  • Вам также нужно управлять выделение памяти вручную. А также есть вероятность, что ваша программа будет испытывать утечку памяти, если это не выполняется должным образом. В С# каждый объект собирает мусор, автоматически.
  • Декларации и определения классы обычно разделяются в заголовочный файл (.h) и исходный файл (.cpp или .cc). Это приведет к немного путаницы вначале.
  • У вас не будет так много базового класса поддержка библиотеки в С++, как в С#. Для Например, у вас не будет HttpRequest, встроенный в С++.
  • Следовательно, вам придется использовать много внешних библиотек и знаю как обращаться с .dll или .lib.
  • С++ не имеет Interface, как в С#. Вы будет использовать абстрактный класс (и множественное наследование). Строка
  • в С++ - это массив char или указатель на char.
  • Есть некоторые алгоритмы и данные структура, доступная для использования в Стандартный шаблон Libary (STL.) Но вам нужно время, чтобы учиться перед вами может начать использовать его эффективно:)

Вы также можете изучить С++/CLI, чтобы объединить ваш код .NET и собственный С++ вместе, чтобы получить лучшее из мира.


Я настоятельно рекомендую: "Эффективный С++ и более эффективный С++". И если вы на это, "Эффективная STL" может быть полезной:)

Эти книги были написаны специально для умных программистов, которым нужно эффективно обрабатывать С++. Я подтверждаю, что эффективный С++ был тем, который мне очень помог, когда я начал С++!

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

удачи:)


Ну, я уже более 10 лет использую С++, так что я бы ответил, изучая строгий контроль памяти, шаблоны С++, STL, затем Boost. Это займет у вас несколько месяцев, затем nitty gritty скажет вам 5 лет:)

Что касается книг, мне нравится Herb Sutter Исключительный С++ и более исключительный С++


Я перешел из Asm в C, С++,... и совсем недавно С#. Это облегчает возможность создания объектов и просто возвращает их из метода или свойства. Как правило, ни реализация, ни код пользователя не должны беспокоиться о том, чтобы освободить эту память. Кроме того, нет причин возвращать код состояния, например HRESULT, в большинстве случаев, потому что если есть проблема, вы бросаете исключение и позволяете коду пользователя обрабатывать его, если он хочет.

Недавно вернувшись к исходному С++-коду для моего последнего проекта, я действительно пропустил сбор мусора и выброс исключений.

Тем не менее, мне нравятся возможности С++ templating. С# должен однажды расширить эту технику.


Хммм... Жесткий. Если вы в порядке с .NET и указателями, не должно быть слишком много нового.

Я думаю, что работа с файлами заголовков С++ будет опытом. Там также С++ STL, чтобы познакомиться с вами.

Возможно, вам также придется иметь дело с людьми, которые кричат ​​на вас о таких вещах, как множественное наследование.


Я вижу, что несколько человек указывают на управление памятью как на большую проблему, потому что вам придется делать это вручную. Ну, не верьте им, это неправильно. Если вы не находитесь в экзотической/старомодной среде, на С++ есть инструменты, которые помогают нам управлять памятью (а также любыми другими ресурсами) неявно и детерминистически. См. Boost/std:: tr1 shared_ptr <> и RAII.

Большая разница с собранной памятью GC: вам придется самим заниматься циклами.

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

Мне нужно согласиться с сообщением pheze: Ускоренный С++ должен быть прочитан, если вы хотите научить вас, как С++ может (/должен?) использоваться.


У Jalf это абсолютно правильно - с фона C/С#, вы практически уже знаете все базовые С++, которые вам нужны, и вы тоже знаете ООП, поэтому вы так же хороши, как и сделали.

Есть две вещи, которые приходят на ум, которые будут для вас новыми:

  • RAII: это позволяет вам автоматически управлять памятью, вам больше не нужно забывать освобождать все, что вы malloc. Круто, да! Он также помогает с любым другим ресурсом, вам больше не нужно забывать закрыть этот сокет, файл, соединение с БД - RAII делает это за вас. Ни C, ни С# не имеют этого.

  • STL/Boost: это "библиотека классов С++", полная полезных утилит и бит. Все стандартные контейнеры находятся в STL (например, "словари" и "массивы" и "списки" ) вместе с алгоритмами, которые вы можете применить к ним (например, если у вас есть список элементов данных, вы можете предоставить небольшой объект функции (называемый функтор), а затем передать оба алгоритма общего характера. Это действительно мощно, вы можете сделать тонну работы, используя его).


Основное отличие заключается в том, что С++ основан на значении, а С# - на основе ссылок.

В С#, когда вы передаете объект методу, вы фактически просто передаете ссылку, поэтому вызывающий и вызываемый методы смотрят на один и тот же объект.

В С++, когда вы передаете объект методу, создается копия этого объекта, и вся копия передается методу. Изменения, внесенные вызываемым методом в копию, не влияют на оригинал в вызывающем методе. Образное поведение можно моделировать на С++ с использованием ссылочного синтаксиса:

void somemethod(someclass& obj);


  • Управление памятью
  • Более сложный синтаксис
  • Управление памятью
  • Меньше поддержки инструмента, чем С# для всего жизненного цикла ООП.
  • Управление памятью

И я упомянул об управлении памятью?

Я всегда считал интересным использовать рынок как показатель воспринимаемых потребностей части населения. Учитывая (для контраста) рынок VB, казалось бы, что компоненты библиотек являются основным акцентом. Однако с самых ранних дней доминирующими предложениями на рынке С++ (и C), по-видимому, были управление памятью, обнаружение утечки и инструменты для улучшения качества кода (например, линт-подобные инспекторы).


Как уже сообщалось, вы, вероятно, будете нести ответственность за управление памятью, но другие, а затем просто изучаете библиотеки С++ и как их включать, я думаю, что это не должно быть сложным переключателем вообще.


Самое большое "препятствие", вероятно, будет заключаться в том, что вы будете нести ответственность за освобождение выделенной вами памяти


Что касается различий в реализации языка - и я думаю, что вам нужно быть осторожными с такими вещами, как управление памятью, объявления в заголовках и т.д. - я думаю, что самое сложное в этом дело - это дополнительная перегрузка специальных символов в синтаксисе. После многих лет написания кода на С# то, что я натыкаюсь на большинство, - это те дополнительные *, & и <>. Моя первая реакция заключается в том, что код на С++ очень похож на большое регулярное выражение.

Я уверен, что как только вы его используете некоторое время, это исчезнет, ​​но я больше не делаю С++, чтобы быть удобным, что я точно знаю, какой символ использовать в каждом случае - я передаю указатель или ссылку на этот объект?

Другая большая ошибка, при любом прочтении кода других людей, - это перегрузка оператора. Я знаю, что вы можете сделать это на С#, но я редко видел, как это было сделано. Может быть, все изменилось, но я часто видел перегрузку оператора на С++, где +/- использовал некоторые странные эффекты. Помимо некоторых довольно очевидных побед (например, конкатенации строк), я считаю, что это действительно сомнительная функция, с которой я мог обойтись - как на С++, так и на С#.


Циклические ссылки между классами [в С++]. ООП на С++ действительно наполовину испечен, если вы спросите меня.

edit: Ладно, так что некоторые подробности в порядке, я полагаю. Скажем, у вас есть: класс Foo и класс Blah. Класс Blah ссылается на класс Foo, класс Foo ссылается на класс Blah. Предположим, вы идете наивный маршрут, который вы можете реализовать так:

#include <blah.h>
class Foo {
 Blah blah;
 ...
}
</blah.h>

и Бла:

#include <foo.h>
class Blah {
 Foo foo;
 ...
}
</foo.h>

Вероятно, это не сработает. Вместо этого вам нужно использовать прямые ссылки, то есть Foo становится:

class Blah;
class Foo {
 Blah blah;
 ...
}

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

licensed under cc by-sa 3.0 with attribution.