В чем может быть разница при переходе с C & C # на C ++? - PullRequest
4 голосов
/ 24 декабря 2008

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

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

Ответы [ 14 ]

14 голосов
/ 24 декабря 2008

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

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

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

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

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

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

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

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

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

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

8 голосов
/ 24 декабря 2008

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

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

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

4 голосов
/ 24 декабря 2008

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

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

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

удачи :) 1007 *

3 голосов
/ 24 декабря 2008

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

Что касается книг, мне нравятся «Исключительные C ++» Херба Саттера и «Больше исключительных C ++»

2 голосов
/ 24 декабря 2008

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

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

Однако мне нравятся шаблонные возможности C ++. C # должен однажды расширить эту технику.

2 голосов
/ 24 декабря 2008

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

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

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

1 голос
/ 24 декабря 2008

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

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

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

void somemethod(someclass& obj);
1 голос
/ 24 декабря 2008

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

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

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

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

1 голос
/ 24 декабря 2008

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

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

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

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

0 голосов
/ 24 декабря 2008

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

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

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

и Бла:

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

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

class Blah;

class Foo {
    Blah blah;
    ...
}

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

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