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

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

Ответы [ 27 ]

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

Понимание указателей в C / C ++

Прежде чем понять, как работают указатели, необходимо понять, как переменные хранятся и доступны в программах. Каждая переменная состоит из 2 частей: (1) адрес памяти, где хранятся данные, и (2) значение хранимых данных.

Адрес памяти часто называют lvalue переменной, а значение хранимых данных называют rvalue (l и r означают левый и правый).

Рассмотрим утверждение:

int x = 10;

Внутренне программа связывает адрес памяти с переменной x. В этом случае давайте предположим, что программа назначает x для размещения по адресу 1001 (не реалистичный адрес, но выбранный для простоты). Следовательно, lvalue (адрес памяти) x равно 1001, а rvalue (значение данных) x равно 10.

Доступ к r-значению осуществляется с помощью переменной «x». Для доступа к lvalue необходим оператор «address of» (‘&’). Выражение ‘& x’ читается как «адрес x».

Expression          Value
----------------------------------
x                   10
&x                  1001

Значение, сохраненное в x, может быть изменено в любое время (например, x = 20), но адрес x (& x) никогда не может быть изменен.

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

Создание указателя на «x» выполняется следующим образом:

int* xptr = &x;

«int *» сообщает компилятору, что мы создаем указатель на целочисленное значение. Часть «= & x» сообщает компилятору, что мы присваиваем адрес x значению xptr. Таким образом, мы сообщаем компилятору, что xptr «указывает» на x.

Предполагая, что xptr назначен адресу памяти 1002, память программы может выглядеть следующим образом:

Variable    lvalue    rvalue
--------------------------------------------
x           1001      10   
xptr        1002      1001

Следующий фрагмент головоломки - это «оператор косвенного обращения» (‘*’), который используется следующим образом:

int y = *xptr;

Оператор косвенного обращения указывает программе интерпретировать значение xptr как адрес памяти, а не как значение данных. То есть программа ищет значение данных (10), сохраненное по адресу, предоставленному xptr (1001).

Собираем все вместе:

Expression      Value
--------------------------------------------
x                   10
&x                  1001
xptr                1001
&xptr               1002
*xptr               10

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

int x = 10;
int *xptr = &x;

printf("x = %d\n", x);
printf("&x = %d\n", &x);        
printf("xptr = %d\n", xptr);
printf("*xptr = %d\n", *xptr);

*xptr = 20;

printf("x = %d\n", x);
printf("*xptr = %d\n", *xptr);

Для вывода вы увидите (Примечание: адрес памяти будет отличаться каждый раз):

x = 10
&x = 3537176
xptr = 3537176
*xptr = 10
x = 20
*xptr = 20

Обратите внимание, как назначение значения для * xptr изменило значение x. Это связано с тем, что «* xptr» и «x» относятся к одной и той же ячейке памяти, о чем свидетельствуют «& x» и «xptr», имеющие одинаковое значение.

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

Указатели и классы не являются действительно сложными темами в C ++. Они довольно фундаментальные.

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

Итак:

int foo = 3;           // integer
int* bar = &foo;       // assigns the address of foo to my pointer bar

С помощью поля моего указателя (столбца) у меня есть выбор: посмотреть адрес внутри поля. (Который является адресом памяти foo). Или я могу манипулировать тем, к чему у меня есть адрес. Эта манипуляция означает, что я следую за этой стрелкой к целому числу (foo).

*bar = 5;  // asterix means "dereference" (follow the arrow), foo is now 5
bar = 0;   // I just changed the address that bar points to

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

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

Эта ссылка содержит видео, описывающее, как работают указатели, с глиняцией. Информативно и легко усваивается.

Эта страница содержит полезную информацию об основных классах.

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

Раньше у меня была проблема с пониманием указателей на паскале :) Когда я начал делать указатели на ассемблере, это был действительно единственный способ получить доступ к памяти, и это просто поразило меня. Это может звучать как дальний удар, но пробовать ассемблер (который всегда является хорошей идеей, чтобы попытаться понять, что на самом деле думают о компьютерах), вероятно, научит вас указателям. Занятия - ну, я не понимаю твоей проблемы - твое обучение в школе было чисто структурированным? Класс - это просто логический способ взглянуть на реальные модели жизни - вы пытаетесь решить проблему, которая может быть обобщена в ряде объектов / классов.

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

Указатели и классы - это совершенно разные темы, поэтому я бы не стал смешивать их вместе, как это. Из этих двух я бы сказал, что указатели являются более фундаментальными.

Хорошим упражнением для изучения указателей является следующее:

  1. создать связанный список
  2. переберите его от начала до конца
  3. переверните его так, чтобы голова теперь была спиной, а спина теперь была головой

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

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

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

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

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

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

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

[править] пересматривая последний абзац - я думаю, это была моя самая точная аналогия за всю историю!

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

Указатели уже, кажется, обращены (не каламбур) в других ответах.

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

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

Чтобы понять указатели, я не могу рекомендовать книгу K & R достаточно высоко.

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

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

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

Второе, что помогло, было в моем классе системного анализа, где мне пришлось создавать http://www.agilemodeling.com/artifacts/classDiagram.htm">UML диаграммы классов. Они, которые я только что нашел, помогли мне понять структуру классов в программе.

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

Мой лучший совет: много практики, и чем больше вы программируете, тем лучше вы это понимаете.

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

Для указателей:

Я нашел в этом посте было очень вдумчивое обсуждение указателей. Может быть, это поможет. Вы знакомы с такими ссылками, как в C #? Это то, что на самом деле относится к чему-то еще? Это, вероятно, хорошее начало для понимания указателей.

Кроме того, посмотрите на пост Кента Фредрика ниже о другом способе познакомиться с указателями.

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