Размышление в C++?

Язык программирования, который я использую, был Java. Я переходил к C++, который был несколько скалистым. "Скалистость" не находится в учении лишь больше вроде "Размышления в C++".

Я видел, что многие люди говорят, что необходимо изучить C сначала (я технически уже знаю это), и затем я вижу, что люди говорят, что никакой пропуск C и не переходит прямо к C++. Еще раз это не проблема "изучения"; это - "взгляды в" проблеме; я знаю синтаксис к C++, я знаю OOD в C++ и т.д.

Например, этот код в SDL, я могу объяснить это, как будто я знаю это, но я не могу действительно "воспользоваться преимуществом" указателей:

SDL_Surface* hello = NULL;

Я должен программировать в C, который "привыкнет" к этому? Что я должен делать для привыкания к указателям, если я никогда не использовал их прибывающий из языка, такого как Java?

19
задан Mat 4 November 2011 в 11:52
поделиться

11 ответов

Должен ли я программировать на 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-> для имитации поведения объекта, подобного указателю (и когда не стоит этим злоупотреблять).

  • Указатели и constness / mutability: в чем разница между указателем, const-указателем, указателем на const-значение и const-указателем на const-значение (и когда использовать каждый из них), а также аналогичное использование mutable-указателей.

Текущая лучшая практика C++ советует не использовать указатели в коде, если только они не управляются автоматически вашим кодом (например, через RAII).

6
ответ дан 30 November 2019 в 02:44
поделиться

Это правда, что указатели - большое дело, и C и C++ разделяют эту концепцию.

Но C++ - это не просто C с объектами.

Есть две бесплатные книги, которые вы можете скачать с Planet PDF, написанные Брюсом Эккелем, под названием Thinking in C++ (тома I и II), которые действительно помогут вам понять смысл C++.

Большую часть C++ также составляет инструментарий, будь то стандартная библиотека (std) или MFC, или классы из библиотеки антигравитационной геометрии, или что-то еще. Это тоже имеет значение.

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

13
ответ дан 30 November 2019 в 02:44
поделиться

Если вы понимаете синтаксис, то единственный способ «свободно» владеть языком - это использовать его.

Использование 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.

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

13
ответ дан 30 November 2019 в 02:44
поделиться

Я не думаю, что изучение C поможет вам в "мышлении" на C ++ ". Как правило, вам просто нужно привыкнуть к определенным концепциям C ++ и тому, почему они полезны.

Ключевыми из них являются интеллектуальные указатели (в более общем смысле RAII ) и огромные шаблоны.

Также имейте в виду, что c ++ - это мультипарадигмальный язык, а не строго ООП. Лучшее решение вообще не очень объектно-ориентировано (STL - отличный пример того, что шаблоны лучше спроектированы, чем объектно-ориентированные).

6
ответ дан 30 November 2019 в 02:44
поделиться

Знаете, есть очень известная книга, которая на самом деле называется "Thinking in C++" :) Даже лучше, она бесплатная! Она должна помочь вам понять такие вещи, как указатели, на более глубоком уровне - она явно направлена на это.

3
ответ дан 30 November 2019 в 02:44
поделиться

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

У моей подруги были проблемы с указателями, когда она начинала изучать C++, и она рекомендует книгу под названием Understanding Pointers in C.

Что такого можно узнать об указателях, что специфично для "мышления на C++"?

  • Указатели могут быть установлены в NULL (т.е. 0). Это может быть сказочно полезно для моделирования ситуаций, когда вы можете иметь значение.
  • Указатели можно переназначать на новые объекты - в отличие, скажем, от ссылок, которые инициализируются только один раз и не могут быть переназначены после инициализации.
  • Указатели можно неявно передавать (от производных классов к базовым).
  • Указатели могут быть явно переданы вниз от базовых классов к производным. Это можно сделать с помощью static_cast если вы случайно знаете, что на самом деле представляет собой производный класс! Обычно люди делают это с помощью dynamic_cast для дополнительной проверки вменяемости во время выполнения.
  • Указатели могут быть приведены к void* и от него, если вы хотите передать кому-то указатель, но не хотите, чтобы он знал тип объекта, на который вы указываете. Другими словами, указатели можно сделать непрозрачными.
  • Указатели и массивы почти эквивалентны.

Вот некоторые вещи, связанные с указателями, которые уникальны для C++ по сравнению с C:

  • В C++ есть понятие ссылок, которые могут использоваться во многих ситуациях, в которых используются указатели, но их гораздо сложнее испортить (в смысле разыменования недопустимого адреса), чем указатели.
  • В C++ есть понятие указателей на функции-члены, которое несколько отличается от указателей на функции, которые также есть в C.
  • В C++ вы можете определять собственные объекты, которые ведут себя как указатели - т.е. которые можно разыменовывать с помощью унарного оператора *. Библиотеки C++ используют эту возможность для реализации интеллектуальных указателей, которые представляют собой целую категорию объектов, которые ведут себя как указатели, но в них также встроен некоторый уровень управления доступом или владением.
2
ответ дан 30 November 2019 в 02:44
поделиться

Этот вопрос не имеет ничего общего с мышлением на C ++ . Вам просто нужно узнать больше о C ++. Хорошо, что вы уже знаете Java, потому что почти все важное в Java непосредственно присутствует в C ++ (и действительно заимствовано из него или находится под влиянием), поэтому вам просто нужно больше изучить C ++, чтобы научиться «отображать» эти идеи дизайна Java в Реализации C ++.

Не учите C, чтобы изучать C ++. Это глупый миф. Это два разных языка. Изучите C ++, чтобы изучить C ++.

1
ответ дан 30 November 2019 в 02:44
поделиться

Язык программирования - это просто инструмент. Суть в том, что чем больше вы знаете, тем лучше. C - очень хороший язык для изучения IMO по тем же причинам, что один из соучредителей stack overflow (Джоэл Спольски) упоминает в этой статье: http://www.joelonsoftware.com/articles/CollegeAdvice. html . Я прочитал эту статью до того, как закончил учебу, и решил последовать его советам по изучению Си до того, как я закончу учебу.

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

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

Наконец, моя степень не требовала от меня прохождения курса компиляторов. Я мог бы уклониться от него, но, поскольку это один из самых трудных уроков, я чувствовал, что был бы менее мужчиной, если бы не взял его. У меня были ужасные оценки, но я узнал так много важных вещей в этом классе, что это стоило пресловутой скалы, которую я привязал к своему среднему баллу, получая его. Если вы узнаете, как на самом деле реализован язык программирования, у вас будет огромное преимущество перед простым знанием того, как работать с «языком X». Любому языку программирования нужно время, чтобы выучить его, даже если у вас есть все основы мира. Случайные придурки повсюду будут пытаться сказать вам, насколько легко выучить `` язык X '', но эти люди обычно просто не уверены в себе и хотят почувствовать себя хорошо, ведя себя так, как будто они родились со способностью программировать на `` языке X '', когда на самом деле они просто потратили часы, чтобы научиться этому. Никто не рождается с этим знанием, просто дайте себе время, чтобы научиться, но будьте умны. Разработайте систематический метод изучения нового языка (моя стратегия всегда начинается с написания на языке «привет, мир»), и у вас все будет хорошо. КОНЕЦ ЗАЯВКИ.

3
ответ дан 30 November 2019 в 02:44
поделиться

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

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

Вторя Эвану Думать на C++?, C++ - это мультипарадигмальный язык. Думать на C++ - это в основном думать в парадигмах. Например, libtiff полностью основан на указателях функций, а COM - полностью на ООП, не использующем ничего, кроме указателей, vtables и подсчета ссылок. В MFC многие вещи обернуты в макросы и таблицы.

В начале проекта у вас есть шанс выбрать правильную парадигму. Иногда она ограничена требованиями проекта, особенно если требуется взаимодействие с внешней средой. Как только проект начнет работать, переключиться будет сложно. Часто выбор был сделан по веской причине.

Единственный способ узнать о парадигме - это поработать в проекте, который ее использует.

0
ответ дан 30 November 2019 в 02:44
поделиться

Если вы действительно думаете об освоении концепции указателей, я предлагаю эту книгу:

Понимание указателей в C от Йешванта Каниткара .

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

0
ответ дан 30 November 2019 в 02:44
поделиться

На мой взгляд, C ++ как язык настолько сложен, что его понимание все еще развивается. Я все еще открываю для себя новые техники программирования. И C больше не является хорошим введением в C ++. Фактически, если вы слишком углубитесь в C, вы научитесь плохим привычкам C ++ и не сможете увидеть некоторые из действительно полезных вещей в C ++. Например, в C ++ я считаю указатели более важными, чем в Java, но не так сильно, как в C.

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

Вот мой личный список важных идей C ++, с которыми вам следует практиковаться и привыкать к использованию:

  • Использование swap (и в C ++ 0x конструктора перемещения и оператора присваивания) для написания код с надежной гарантией исключения.
  • Метапрограммирование шаблонов (шаблоны - это, по сути, функциональный язык внутри C ++, вывод которого - программа на C ++).
  • Идиома RAII (RAII означает получение ресурсов - это инициализация) - это то, что в C ++ принципиально отличается от Java и очень важно для понимания.
  • И, относящийся к RAII, концепция, согласно которой объекты непримитивных типов обычно создаются без использования new . Вы создаете объекты прямо в стеке или ссылаетесь на них путем включения, а не по ссылке.Это огромное, но тонкое отличие от Java.
  • Итераторы - то, во что по большей части превратилось использование указателей не в Javaesque
  • И действительно, указатели, которые не используются в качестве итераторов, ничем не отличаются от переменных непримитивных типов (т.е. Объект ) в Java, за исключением отсутствия сборки мусора.
1
ответ дан 30 November 2019 в 02:44
поделиться