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





Самым большим "препятствием", вероятно, будет то, что вы будете нести ответственность за высвобождение выделенной памяти.
Хммм ... Крутой. Если вас устраивает .NET и указатели, не должно быть слишком много нового.
Я думаю, что работа с заголовочными файлами C++ будет интересной. Также есть C++ STL, с которым можно познакомиться.
Возможно, вам также придется иметь дело с людьми, кричащими вам о таких вещах, как множественное наследование.
Как уже сообщалось, вы, вероятно, будете нести ответственность за управление своей памятью, но кроме изучения библиотек C++ и их организации, я думаю, что это не должно быть жестким переключением.
Я настоятельно рекомендую: «Эффективный C++ и более эффективный C++». И если вы в этом заинтересованы, "Эффективный STL" может вам помочь :)
Эти книги написаны специально для умных программистов, которым необходимо эффективно работать с C++. Я подтверждаю, что именно Эффективный C++ очень помог мне, когда я начал заниматься C++!
Еще одна хорошая книга для новичка в C++ (но я не думаю, что компьютерный новичок) - это «Accelerated C++». Он ориентирован в первую очередь на хорошее кодирование, stl и создание высокоуровневого кода, а не на деталях. (об этом подробнее в конце книги).
удачи :)
Что ж, я использую C++ уже более 10 лет, поэтому мой ответ был бы: изучение строгого управления памятью, шаблоны C++, STL, а затем Boost. Это должно занять у вас несколько месяцев, а затем, скажем, 5 лет :)
Из книг мне нравятся Exceptional C++ Херба Саттера и More Exceptional C++.
Хм ... каждый день узнаешь что-то новое. Какие аспекты управления памятью являются новыми в C++ по сравнению с обычным C? У меня создалось впечатление, что все гадости уже написаны на C.
Для начала вы используете new / delete, в отличие от malloc / free, затем у вас есть перегрузка new / delete, затем у вас есть распределители экземпляров, распределители классов, умные указатели в изобилии, чтобы назвать несколько очевидных.
Спасибо! Теперь я знаю, на что нужно обратить внимание, когда вернусь к C++.
Вы правы, неприятные вещи уже есть в C. Довольно ошибочно говорить программисту на C, что «В C++ вам нужно научиться управлению памятью». C++ просто добавляет различные способы обертывания выделения памяти.
Вот некоторые с моей точки зрения:
HttpRequest, встроенный в C++.Interface, как в C#. Ты
будет использовать абстрактный класс (и
множественное наследование).Вы также можете изучить C++ / CLI, чтобы смешивать код .NET и собственный C++ вместе, чтобы получить лучшее из обоих миров.
Если он раньше работал с C, то указатели и управление памятью преподнесут несколько сюрпризов.
Я категорически не согласен с пунктами 1 и 2. В современном C++ вы никогда не используете delete и редко используете new. Управление памятью осуществляется через RAII. Я испытал утечки памяти более в C#, чем в C++ на самом деле.
@Alexandre По общему признанию, в то время я не знал о некоторых лучших практиках современного C++. Теперь, когда я видел все больше и больше утечек памяти в приложениях C# и C++, я знаю, что их одинаково сложно отследить :(
Что касается различий в реализации языка - и я думаю, что вам нужно быть осторожным с такими вещами, как управление памятью, объявления в заголовках и т. д. - я думаю, что сложнее всего иметь дело с дополнительной перегрузкой специальных символов в синтаксис. После многих лет написания кода на C# я больше всего спотыкаюсь о лишних *, & и <>. Моя первая реакция заключается в том, что код C++ очень похож на большое регулярное выражение.
Я уверен, что после того, как вы его некоторое время использовали, это исчезнет, но я больше не делаю достаточно C++, чтобы чувствовать себя комфортно, потому что я точно знаю, какой символ использовать в каждом случае - я передаю указатель или ссылка на этот объект?
Другая большая проблема, в любом случае при чтении чужого кода, - это перегрузка операторов. Я знаю, что вы можете сделать это на C#, но я редко видел, чтобы это было сделано там. Возможно, что-то изменилось, но я часто видел перегрузку операторов в C++, где +/- принимал некоторые странные эффекты. Помимо некоторых довольно очевидных побед (например, конкатенации строк), я думаю, что это действительно сомнительная функция, без которой я мог бы обойтись как в C++, так и в C#.
Я перешел от Asm к C, C++, ... и совсем недавно C#. Это облегчает возможность создавать экземпляры объектов и просто возвращать их из метода или свойства. Как правило, ни реализация, ни пользовательский код не должны беспокоиться об освобождении этой памяти. Кроме того, в большинстве случаев нет причин возвращать код состояния, такой как HRESULT, потому что, если есть проблема, вы генерируете исключение и позволяете пользовательскому коду обрабатывать его, если он хочет.
Недавно переключившись на собственный код C++ для моего последнего проекта, я действительно скучаю по сбору мусора и выбрасыванию исключений.
Однако мне нравятся возможности C++ по созданию шаблонов. Когда-нибудь C# расширит эту технику.
Почему вы не используете исключения C++?
Собственная обработка исключений C++ не так мощна, как в CLR. Я не нашел в этом особого применения, так как привык генерировать исключения способом CLR.
И я уже говорил об управлении памятью?
Я всегда считал интересным использовать рынок как индикатор предполагаемых потребностей определенного сегмента населения. Учитывая (для контраста) рынок VB, может показаться, что библиотеки компонентов являются основным акцентом. Однако с самых первых дней доминирующими предложениями на рынке C++ (и C), похоже, были инструменты управления памятью, обнаружения утечек и качества кода (например, lint-подобные инспекторы).
Я вижу, как несколько человек указывают на управление памятью как на большую проблему, потому что вам придется делать это вручную. Что ж, не верьте им, это неправильно. Если вы не находитесь в экзотической / старомодной среде, в C++ есть инструменты, которые помогают нам управлять памятью (а также любыми другими ресурсами) неявно и детерминированно. См. Boost / std :: tr1 shared_ptr <> и RAII.
Большая разница с памятью, собираемой сборщиком мусора: вам придется позаботиться о циклах самостоятельно.
Что касается множественного наследования, как только вы поймете, что подразумевает LSP, это тоже не проблема.
Я должен согласиться с сообщением фез: Ускоренный C++ необходимо прочитать, если вы хотите научить вас, как можно (/ нужно?) Использовать C++.
Циклические ссылки между классами [в C++]. ООП в C++ действительно наполовину готов, если вы спросите меня.
edit: Хорошо, я полагаю, что некоторые подробности в порядке. Скажите, что у вас есть: класс Foo и класс Blah. Класс 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++", вы поймете, почему я упомянул об этом в этом вопросе. А теперь перестань голосовать за меня, ладно ...
Не уверен, почему вы думаете, что C# не может иметь циклических ссылок. Излишне говорить, что вы ошибаетесь (blogs.msdn.com/nickmalik/archive/2005/03/18/398601.aspx).
Хм, нет, я говорю о циклических ссылках между классами в C++, т.е. о необходимости не просто слепо включать файлы заголовков, думая, что они похожи на простой импорт. Я отредактирую свой вопрос, чтобы отразить это.
Основное различие, о котором я могу думать, заключается в том, что C++ является гораздо более многопарадигмальным языком, чем C и C#. В C# ООП по-прежнему является парадигмой то. Это язык ООП прежде всего, и если вы не используете ООП, сообщество C# скажет вам, что вы делаете это неправильно. (хотя в C# за последние несколько лет добавлена неплохая поддержка некоторых элементов функционального программирования).
В C++ ООП, в общем, поддерживается, и вы можете использовать его, когда захотите, но вся суета связана с общим программированием. Шаблоны C++ позволяют использовать широкий спектр умных, многоразовых и универсальных библиотек и достигают многих из тех же целей, что и старомодное ООП, но без больших иерархий наследования и практически без связи между классами. Стандартная библиотека содержит множество примеров этого
В C++ многие конструкции C, хотя и законные, в основном избегаются:
boost::shared_ptr или std::auto_ptr, или ссылкамиКонечно, для каждого из этих пунктов есть исключения, но, как правило, код C++, в отличие от кода C, почти полностью исключает их использование.
И в большей степени, чем в C#, классы действительно являются рабочими лошадками, выполняющими большую часть тяжелой работы. В C# класс - это не что иное, как каркас, контейнер, в который помещаются все ваши методы. Конечно, у него есть конструктор, и он май реализует Dispose (); но C++ идет намного дальше, и у вас есть:
Деструктор, вероятно, является наиболее важным понятием в C++. Это жизненно важно для RAII, так как это способ управления памятью или другими ресурсами, потому что он автоматически вызывается, когда объект выходит за пределы области видимости. Это позволяет вашим классам давать множество гарантий, которых невозможно достичь на C или C#. Например, boost :: thread предоставляет ограниченные блокировки, которые гарантированно снимаются, когда выходит за пределы области видимости, независимо от того, возвращается ли функция нормально, генерируется исключение или что-то еще. Поэтому при использовании этой библиотеки пользователю не нужно беспокоиться о снятии блокировок или других ресурсов. Это происходит автоматически, как только вы закончите с ними.
В некотором смысле это дает вам гораздо больше возможностей для настройки поведения вашего класса. В отличие от C#, вы точно контролируете, что происходит при выполнении простого присваивания. Вы контролируете, что происходит, когда класс выходит за пределы области видимости, когда он инициализируется с нуля или как копия другого объекта. Это делает практически невозможным неправильное использование хорошо написанного класса. (Почти)
Помимо этого, вы, вероятно, столкнетесь с концепциями шаблонов и их метапрограммирования. Это чрезвычайно мощные инструменты, поэтому убедитесь, что вы в дружеских отношениях с ними. :)
Джалф совершенно прав - имея опыт работы с C / C#, вы практически уже знаете весь базовый C++, который вам нужен, и вы также знаете ООП, так что вы так же хороши, как и сделали.
Однако есть 2 вещи, которые будут для вас новыми:
RAII: это позволяет вам автоматически управлять памятью, вам больше не нужно помнить о том, чтобы освободить все, что вы заблокировали. Круто, да! Это также помогает с любым другим ресурсом, вам больше не нужно помнить о закрытии этого сокета, файла, соединения с БД - RAII сделает это за вас. Ни в C, ни в C# этого нет.
STL / Boost: это «библиотека классов C++», полная полезных утилит и битов. Все стандартные контейнеры находятся в STL (например, «словари», «массивы» и «списки») вместе с алгоритмами, которые вы можете применить к ним (например, если у вас есть список элементов данных, вы можете предоставить небольшой функциональный объект (называемый функтор), а затем передать оба в общий алгоритм. Это действительно мощный инструмент, с его помощью можно проделать массу работы).
Основное отличие состоит в том, что C++ основан на значениях, а C# - на ссылках.
В C#, когда вы передаете объект методу, вы фактически просто передаете ссылку, поэтому вызывающий метод и вызываемый метод смотрят на один и тот же объект.
В C++, когда вы передаете объект методу, создается копия этого объекта, и вся копия передается методу. Изменения, внесенные вызываемым методом в копию, не влияют на оригинал в вызывающем методе. Эталонное поведение можно смоделировать на C++, используя эталонный синтаксис:
void somemethod(someclass& obj);
Я бы сказал, что эталонное поведение можно получить с помощью указателей, но ссылки предлагают лучшее решение. Мое объяснение состоит в том, что, хотя они называются ссылками, как в Java, так и в C# указатели Рекомендациинаходятся
Я не уверен, почему вы называете & ссылки симуляцией, поскольку они являются ключевой и оригинальной особенностью C++, а не каким-то неясным расширением.
Это «моделирование», потому что справочный синтаксис не делает C++ языком справочников, но дает многие из тех же функций.
он исходит из фона C, в C++ меньше управления памятью, не больше.