В C ++ я не могу понять указатели и классы - PullRequest
7 голосов
/ 18 сентября 2008

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

Ответы [ 27 ]

1 голос
/ 19 сентября 2008

Нет никакой замены для практики.

Легко читать книгу или слушать лекцию, и вы чувствуете, что следите за происходящим.

Я бы порекомендовал взять некоторые примеры кода (я предполагаю, что они где-то есть на диске), скомпилировать их и запустить, а затем попытаться изменить их, чтобы сделать что-то другое.

  • Добавить еще один подкласс в иерархию
  • Добавить метод в существующий класс
  • Изменить алгоритм, который повторяется вперед через коллекцию, чтобы пойти вместо этого.

Я не думаю, что есть какая-нибудь книга "Серебряная пуля", которая бы сделала это.

Для меня то, что указывало на то, что означали указатели, работало в ассемблере, и то, что указатель на самом деле был просто адресом, а наличие указателя не означало, что то, на что он указывал, было значимым объектом.

1 голос
/ 19 сентября 2008

Изучите язык ассемблера, а затем выучите C. Тогда вы узнаете, каковы основные принципы машины (и вышеупомянутые указатели).

Указатели и классы являются фундаментальными аспектами C ++. Если вы их не понимаете, это означает, что вы на самом деле не понимаете C ++.

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

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

0 голосов
/ 22 сентября 2008

Указатели не являются чем-то магическим, вы используете их постоянно!
Когда вы говорите:

int a;

и компилятор создает хранилище для 'a', вы фактически говорите, что объявляете
int и хотите назвать его место в памяти 'a'.

Когда вы говорите:

int * a;

вы объявляете переменную, которая может содержать ячейку памяти типа int. Это так просто. Кроме того, не бойтесь арифметики указателей, просто всегда иметь в виду «карту памяти», когда вы имеете дело с указателями и думать с точки зрения хождения по адресам памяти.

Классы в C ++ являются лишь одним из способов определения абстрактных типов данных. Я бы посоветовал прочитать хорошую книгу по ООП, чтобы понять концепцию, а затем, если вам интересно, узнать, как компиляторы C ++ генерируют код для имитации ООП. Но это знание придет со временем, если вы будете придерживаться C ++ достаточно долго:)

0 голосов
/ 19 сентября 2008

Лучшая книга, которую я читал по этим темам, - «Мышление на С ++» Брюса Эккеля. Вы можете скачать его бесплатно здесь .

0 голосов
/ 19 сентября 2008

Вы можете найти эту статью Джоэла поучительной. Кроме того, если вы «работали в C ++ в течение некоторого времени» и получили высшее образование в CS, возможно, вы учились в JavaSchool (я бы сказал, что вы вообще не работали в C ++; вы работал в C, но с помощью компилятора C ++).

Кроме того, просто чтобы подтвердить ответы Ходжу и Нсандерса, указатели очень важны для C ++. Если вы не понимаете указатели, значит, вы не понимаете основ C ++ (кстати, признание этого факта - начало понимания C ++). Точно так же, если вы не понимаете классы, то вы не понимаете основы C ++ (или OO в этом отношении).

Для указателей я думаю, что рисование с помощью ящиков - это хорошая идея, но работа в сборке также является хорошей идеей. Я думаю, что любые инструкции, использующие относительную адресацию, помогут вам понять, что такое указатели довольно быстро.

Что касается классов (и объектно-ориентированного программирования в целом), я бы порекомендовал Stroustrups "The C ++ Programming Language" последнее издание. Это не только канонический справочный материал по C ++, но и немало материала по многим другим вещам, от базовых объектно-ориентированных иерархий классов и наследования вплоть до принципов проектирования в больших системах. Это очень хорошо читается (если не немного густо и кратко в пятнах).

0 голосов
/ 19 сентября 2008

Для указателей и классов, вот моя аналогия. Я буду использовать колоду карт. Колода карт имеет номинал и тип (9 червей, 4 пики и т. Д.). Таким образом, в нашем языке программирования, подобном C ++, «Колода карт» мы скажем следующее:

HeartCard card = 4; // 4 of hearts!

Теперь вы знаете, где находится 4 червы, потому что, черт возьми, вы держите колоду лицом вверх в руке, и она наверху! Итак, что касается остальных карт, мы просто скажем, что «4 червы» в НАЧАЛЕ. Итак, если бы я спросил вас, какая карта в НАЧАЛЕ, вы бы ответили: «Четыре сердца, конечно!». Ну, ты просто "указал" мне, где находится карта. На нашем языке программирования "Колода карт" вы также можете сказать следующее:

HeartCard card = 4; // 4 of hearts!
print &card // the address is BEGINNING!

Теперь переверните колоду карт. Теперь задняя сторона НАЧАЛА, и вы не знаете, что это за карта. Но, скажем, вы можете сделать это как хотите, потому что вы полны волшебства. Давайте сделаем это в нашем языке "Колода карт"!

HeartCard *pointerToCard = MakeMyCard( "10 of hearts" );
print pointerToCard // the value of this is BEGINNING!
print *pointerToCard // this will be 10 of hearts!

Что ж, MakeMyCard («10 червей») - это то, что вы делали свою магию и знали, что хотите указать НАЧАЛО, делая карту 10 червей! Вы переворачиваете свою карту и, вуаля! Теперь * может вас оттолкнуть. Если это так, проверьте это:

HeartCard *pointerToCard = MakeMyCard( "10 of hearts" );
HeartCard card = 4; // 4 of hearts!
print *pointerToCard; // prints 10 of hearts
print pointerToCard; // prints BEGINNING
print card; // prints 4 of hearts
print &card; // prints END - the 4 of hearts used to be on top but we flipped over the deck!

Что касается классов, мы использовали классы в примере, определив тип как HeartCard. Мы знаем, что такое HeartCard ... Это карта со значением и типом сердца! Итак, мы классифицировали это как HeartCard. Каждый язык имеет одинаковый способ определения или «классификации» того, что вы хотите, но все они имеют одну и ту же концепцию! Надеюсь, это помогло ...

0 голосов
/ 19 сентября 2008

Вы читали Бьярн Страуструп Язык программирования C ++ ? Он создал C ++.

C ++ FAQ Lite тоже хорош.

0 голосов
/ 19 сентября 2008

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

Итак, в C / C ++, когда вы объявляете «int» (intA), вы определяете 32-битный кусок памяти, который содержит значение - число. Если затем вы объявляете «указатель int» (intB), вы определяете 32-битный фрагмент памяти, который содержит адрес типа int. Я могу назначить последний, чтобы он указывал на первый, указав «intB = & intA», и теперь 32 бита памяти, определенных как intB, содержат адрес, соответствующий расположению intA в памяти.

Когда вы «разыменовываете» указатель intB, вы просматриваете адрес, хранящийся в памяти intB, находите это местоположение, а затем смотрите значение, хранящееся там (число).

Обычно я сталкиваюсь с путаницей, когда люди теряют понимание того, с чем именно они имеют дело, когда они используют операторы "&", "*" и "->" - это адрес, значение или что ? Вам просто нужно сосредоточиться на том факте, что адреса памяти - это просто местоположения, а значения - это двоичная информация, хранящаяся там.

0 голосов
/ 19 сентября 2008

Одна из вещей, которая действительно помогла мне понять эти концепции, - это изучить UML - унифицированный язык моделирования. Просмотр концепций объектно-ориентированного дизайна в графическом формате действительно помог мне понять, что они означают. Иногда трудно понять эти концепции, просто взглянув на то, какой исходный код их реализует.

Просмотр объектно-ориентированных парадигм, таких как наследование, в графической форме - очень мощный способ понять концепцию.

Мартин Фаулер UML Distilled - хорошее, краткое введение.

0 голосов
/ 19 сентября 2008

Классы относительно легко понять; ООП может занять много лет. Лично я до конца прошлого года не понимал истинного ООП. Жаль, что Smalltalk не так широко распространен в колледжах, как следовало бы. Это на самом деле говорит о том, что ООП - это объекты, торгующие сообщениями, а не классы, являющиеся автономными глобальными переменными с функциями.

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

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