Язык программирования, который я использую, был Java. Я переходил к C++, который был несколько скалистым. "Скалистость" не находится в учении лишь больше вроде "Размышления в C++".
Я видел, что многие люди говорят, что необходимо изучить C сначала (я технически уже знаю это), и затем я вижу, что люди говорят, что никакой пропуск C и не переходит прямо к C++. Еще раз это не проблема "изучения"; это - "взгляды в" проблеме; я знаю синтаксис к C++, я знаю OOD в C++ и т.д.
Например, этот код в SDL, я могу объяснить это, как будто я знаю это, но я не могу действительно "воспользоваться преимуществом" указателей:
SDL_Surface* hello = NULL;
Я должен программировать в C, который "привыкнет" к этому? Что я должен делать для привыкания к указателям, если я никогда не использовал их прибывающий из языка, такого как Java?
Должен ли я программировать на C, чтобы "привыкнуть" к этому?
Нет, не стоит. Си был хорошим введением в C++, когда C++ воспринимался как "Си, но с классами". C++ настолько сильно эволюционировал от этого мышления, что написание кода на C в C++ приводит к очень плохому коду на C++.
Что я должен делать, чтобы привыкнуть к указателям, если я никогда не использовал их.
Знание того, как использовать указатели в C++, подразумевает несколько ключевых областей (и вы, вероятно, должны изучать их одну за другой):
арифметика указателей (сложение и вычитание указателей и целых чисел, использование нулевого указателя, указатели и массивы, операции с указателями); это часть, которую C++ разделяет с C.
указатели на функции (эта часть также разделяется с C).
приведение указателей (static_cast, dynamic_cast, ...). Эта часть специфична для C++. Вы также можете определить свой собственный тип приведения и немного поэкспериментировать с ним (в качестве примера можно посмотреть на boost::lexical_cast).
указатели на объекты-члены и функции-члены.
RAII для указателей и различные реализации умных указателей: указатели с круговой связью, указатели с подсчетом ссылок (boost::shared_ptr), уникальные указатели (std::auto_ptr), скопированные указатели.
обертывание указателей функций в классы-функторы (см. std::tr1::function или boost::function).
объектные ссылки и их сходство и отличие от указателей; где использовать ссылки и где использовать указатели.
сходство между указателями и итераторами.
использование operator*
и operator->
для имитации поведения объекта, подобного указателю (и когда не стоит этим злоупотреблять).
Указатели и const
ness / mutability: в чем разница между указателем, const-указателем, указателем на const-значение и const-указателем на const-значение (и когда использовать каждый из них), а также аналогичное использование mutable-указателей.
Текущая лучшая практика C++ советует не использовать указатели в коде, если только они не управляются автоматически вашим кодом (например, через RAII).
Это правда, что указатели - большое дело, и C и C++ разделяют эту концепцию.
Но C++ - это не просто C с объектами.
Есть две бесплатные книги, которые вы можете скачать с Planet PDF, написанные Брюсом Эккелем, под названием Thinking in C++ (тома I и II), которые действительно помогут вам понять смысл C++.
Большую часть C++ также составляет инструментарий, будь то стандартная библиотека (std) или MFC, или классы из библиотеки антигравитационной геометрии, или что-то еще. Это тоже имеет значение.
Если вам нужен C++, идите на C++. Изучать сначала C - это все равно, что учить испанский, чтобы выучить португальский, вместо того, чтобы стремиться к португальскому.
Если вы понимаете синтаксис, то единственный способ «свободно» владеть языком - это использовать его.
Использование C - хороший способ упростить вещи и приблизиться к «металлическому», но это не то же самое, что C ++, поэтому в конечном итоге я бы посоветовал использовать C ++, если вы хотите изучить C ++. (т. е. не учите латынь, если хотите свободно говорить по-итальянски, хотя латынь даст вам много идей, эти два языка - разные звери, и соответствующие мыслительные процессы, соответственно, различаются)
Указатели очень просты, когда-то вы их «получаете». Очень хорошая идея при использовании указателей - использовать нотацию префикса «p». Для каждого указателя (уровень косвенного обращения) добавьте букву «p» перед именем переменной, чтобы напомнить вам, что это указатель:
Vehicle vehicle = an actual vehicle
Vehicle *pVehicle = a pointer to a Vehicle
Vehicle **ppVehicle = a pointer to a pointer to a Vehicle
Чтобы получить доступ к транспортному средству, вы должны разыменовать один раз для каждого указателя, то есть:
vehicle.SetName("Ford Focus"); // Directly access an object instance
(*pVechicle).SetName("Ford Focus"); // Dereference once
(**ppVehicle).SetName("Ford Focus") // Dereference twice
Есть три способа разыменования (просто разные синтаксисы, которые генерируют идентичный код):
(*pVehicle).DoSomething()
pVehicle->DoSomething()
pVehicle[0].DoSomething()
Когда вы используете арифметические операции с указателями, они работают в единицах Vehicle, а не в байтах, т.е.e
pVehicle++; // Move to the next vehicle record, not just the next byte
И, наконец, для каждого
pVehicle = new Vehicle
вам необходимо сбалансировать свой код с помощью:
delete pVehicle;
pVehicle = NULL;
(edit) О, и почти забыл о самом важном: ВСЕГДА проверяйте, что ваш указатель действителен, прежде чем пытаться используй это!
if (pVehicle != NULL)
...use pVehicle
Я считаю, что обозначение «p» бесценно, поскольку вы никогда не забываете, что что-то является указателем, а количество p говорит вам, сколько разыменований необходимо. Как только я его принял, я перестал писать ошибки разыменования / нарушения доступа NULL.
Это все, что вам нужно знать об указателях. Теперь вам просто нужно использовать их много , чтобы получить беглость.
Я не думаю, что изучение C поможет вам в "мышлении" на C ++ ". Как правило, вам просто нужно привыкнуть к определенным концепциям C ++ и тому, почему они полезны.
Ключевыми из них являются интеллектуальные указатели (в более общем смысле RAII ) и огромные шаблоны.
Также имейте в виду, что c ++ - это мультипарадигмальный язык, а не строго ООП. Лучшее решение вообще не очень объектно-ориентировано (STL - отличный пример того, что шаблоны лучше спроектированы, чем объектно-ориентированные).
Знаете, есть очень известная книга, которая на самом деле называется "Thinking in C++" :) Даже лучше, она бесплатная! Она должна помочь вам понять такие вещи, как указатели, на более глубоком уровне - она явно направлена на это.
Я предлагаю сосредоточиться на темах, с которыми у вас проблемы. Указатели по большей части одинаковы в C и C++, так что выбирайте любой ресурс, который поможет вам больше всего.
У моей подруги были проблемы с указателями, когда она начинала изучать C++, и она рекомендует книгу под названием Understanding Pointers in C.
Что такого можно узнать об указателях, что специфично для "мышления на C++"?
static_cast
если вы случайно знаете, что на самом деле представляет собой производный класс! Обычно люди делают это с помощью dynamic_cast
для дополнительной проверки вменяемости во время выполнения. void*
и от него, если вы хотите передать кому-то указатель, но не хотите, чтобы он знал тип объекта, на который вы указываете. Другими словами, указатели можно сделать непрозрачными. Вот некоторые вещи, связанные с указателями, которые уникальны для C++ по сравнению с C:
Этот вопрос не имеет ничего общего с мышлением на C ++ . Вам просто нужно узнать больше о C ++. Хорошо, что вы уже знаете Java, потому что почти все важное в Java непосредственно присутствует в C ++ (и действительно заимствовано из него или находится под влиянием), поэтому вам просто нужно больше изучить C ++, чтобы научиться «отображать» эти идеи дизайна Java в Реализации C ++.
Не учите C, чтобы изучать C ++. Это глупый миф. Это два разных языка. Изучите C ++, чтобы изучить C ++.
Язык программирования - это просто инструмент. Суть в том, что чем больше вы знаете, тем лучше. C - очень хороший язык для изучения IMO по тем же причинам, что один из соучредителей stack overflow (Джоэл Спольски) упоминает в этой статье: http://www.joelonsoftware.com/articles/CollegeAdvice. html . Я прочитал эту статью до того, как закончил учебу, и решил последовать его советам по изучению Си до того, как я закончу учебу.
В конце концов, программное обеспечение, написанное на любом языке, запускается на (или на) компьютерном чипе. Очень важно понимать (если вы все равно хотите быть «хорошим» программистом), какова стоимость (во времени процессора и программиста) используемых вами механизмов на любом используемом вами языке. Языки высокого уровня отлично подходят для программистов в некоторых случаях, потому что они позволяют реализовать мощные функции конечного пользователя быстрее, чем языки более низкого уровня, такие как C. Однако языки более низкого уровня в целом обеспечивают лучшую производительность.Единственное, что вам, как программисту, нужно подумать, это «какой инструмент лучше всего подходит для работы?» Вы не используете молоток, чтобы вбить винт, бла-бла, вставьте сюда другую аналогию с резаком для плиты и т. Д.
Одна вещь, которую языки высокого уровня обычно скрывают от программиста, - это указатели. Указатели - очень важная концепция, которую необходимо знать независимо от того, программируете ли вы на языке, который их от вас скрывает, или нет. C - отличный язык для изучения указателей (или C ++, если на то пошло). Рекурсия - еще одна большая проблема, но я не думаю, что какой-либо язык действительно может скрыть эту концепцию ...это общая концепция решения проблем, тогда как указатели - это скорее механическая деталь.
Наконец, моя степень не требовала от меня прохождения курса компиляторов. Я мог бы уклониться от него, но, поскольку это один из самых трудных уроков, я чувствовал, что был бы менее мужчиной, если бы не взял его. У меня были ужасные оценки, но я узнал так много важных вещей в этом классе, что это стоило пресловутой скалы, которую я привязал к своему среднему баллу, получая его. Если вы узнаете, как на самом деле реализован язык программирования, у вас будет огромное преимущество перед простым знанием того, как работать с «языком X». Любому языку программирования нужно время, чтобы выучить его, даже если у вас есть все основы мира. Случайные придурки повсюду будут пытаться сказать вам, насколько легко выучить `` язык X '', но эти люди обычно просто не уверены в себе и хотят почувствовать себя хорошо, ведя себя так, как будто они родились со способностью программировать на `` языке X '', когда на самом деле они просто потратили часы, чтобы научиться этому. Никто не рождается с этим знанием, просто дайте себе время, чтобы научиться, но будьте умны. Разработайте систематический метод изучения нового языка (моя стратегия всегда начинается с написания на языке «привет, мир»), и у вас все будет хорошо. КОНЕЦ ЗАЯВКИ.
Если вы уже работаете в проекте на C++ на ежедневной основе, есть шанс, что вы уже привыкли к использованию указателей. Просто требуется больше времени, чтобы знания и повторяющиеся шаблоны усвоились. (Если я правильно помню, один известный гуру C++ говорит, что для того, чтобы стать продуктивным, требуется от 6 месяцев до года.)
Хороший отладчик, особенно тот, который показывает исходный код и скомпилированный код сборки во время выполнения, поможет вам лучше понять.
Вторя Эвану Думать на C++?, C++ - это мультипарадигмальный язык. Думать на C++ - это в основном думать в парадигмах. Например, libtiff полностью основан на указателях функций, а COM - полностью на ООП, не использующем ничего, кроме указателей, vtables и подсчета ссылок. В MFC многие вещи обернуты в макросы и таблицы.
В начале проекта у вас есть шанс выбрать правильную парадигму. Иногда она ограничена требованиями проекта, особенно если требуется взаимодействие с внешней средой. Как только проект начнет работать, переключиться будет сложно. Часто выбор был сделан по веской причине.
Единственный способ узнать о парадигме - это поработать в проекте, который ее использует.
Если вы действительно думаете об освоении концепции указателей, я предлагаю эту книгу:
Понимание указателей в C от Йешванта Каниткара .
Это очень ясная и организованная книга, которая даст вам глубокое понимание указателей , начиная с нуля и заканчивая применением указателей.
На мой взгляд, C ++ как язык настолько сложен, что его понимание все еще развивается. Я все еще открываю для себя новые техники программирования. И C больше не является хорошим введением в C ++. Фактически, если вы слишком углубитесь в C, вы научитесь плохим привычкам C ++ и не сможете увидеть некоторые из действительно полезных вещей в C ++. Например, в C ++ я считаю указатели более важными, чем в Java, но не так сильно, как в C.
Нет волшебной книги, которую вы могли бы прочитать, или формулы, которой вы могли бы следовать, чтобы научиться думать на C ++. Вы должны практиковаться с концепциями. Напишите свои собственные программы, которые их используют, даже если они всего лишь игрушки.
Вот мой личный список важных идей C ++, с которыми вам следует практиковаться и привыкать к использованию:
swap
(и в C ++ 0x конструктора перемещения и оператора присваивания) для написания код с надежной гарантией исключения. new
. Вы создаете объекты прямо в стеке или ссылаетесь на них путем включения, а не по ссылке.Это огромное, но тонкое отличие от Java. Объект
) в Java, за исключением отсутствия сборки мусора.