Лучший способ объяснить декларативную ошибочность в C ++?

StackOverflow https://stackoverflow.com/questions/1360880

  •  20-09-2019
  •  | 
  •  

Вопрос

Как можно было бы сформулировать хорошее объяснение того, почему следующий код неверен, поскольку автор пытается написать код на C ++ декларативно, а не процедурно?

const double NEWTONS_PER_POUND = 4.448;

int main()
{
   double pounds, newtons;
   pounds = newtons/NEWTONS_PER_POUND; /* pounds equals 'unassigned variable'/4.448 */
   newtons = 10.0;
   cout << pounds << endl;             /* a big number, not 10.0/4.448 */
   return 0;
}

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

Я бы объяснил это так: "C ++ является процедурным, и поэтому на момент объявления

pounds = newtons/NEWTONS_PER_POUND;

newtons не было присвоено значение.

Есть предложения получше?Или объяснение, почему C ++ недостаточно "умен", чтобы выполнять поведение, ошибочно ожидаемое пользователем?

Это было полезно?

Решение

Скажите автору, что

pounds = newtons/NEWTONS_PER_POUND;

дает команду процессору

  • возьмите значение по адресу, называемому «ньютоны»
  • возьмите значение по адресу, называемому «NEWTONS_PER_POUND».
  • разделить их
  • сохранить результат по адресу, называемому «фунтами»

то, что он ищет, скорее всего, является функцией в императивных терминах:

double newtons_to_pounds(double newtons) {
  return newtons/NEWTONS_PER_POUND;
}

...

newtons = 10.0;
cout << newtons_to_pounds(newtons) << endl;    /* a big number, not 10.0/4.448 */
return 0;

Другие советы

C++ — это императивный язык программирования, а не средство решения уравнений.

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

Вот подробное объяснение:

double pounds, newtons;
pounds = newtons/NEWTONS_PER_POUND;
newtons = 10.0;

Первый оператор объявляет две переменные без их инициализации.На данный момент их значения не определены.

Второе утверждение считывает значение newtons (которое может быть чем угодно) и делит его на NEWTONS_PER_POUND.Результат (который может быть любым) присваивается pounds.

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

Что ж, это не должно быть слишком сложно объяснить, независимо от происхождения студентов:просто скажите им, что C++ оценивает программы шаг за шагом, оператор за оператором (несмотря на артефакты компилятора, такие как переупорядочение...).

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

Не лениво оценивать ньютоны

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

Если человек не слишком техничен, вы можете попробовать:

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

Объясните, что фунтам присваивается значение в строке с помощью оператора присваивания:

pounds = newtons/NEWTONS_PER_POUND;

Если бы это было не так, а фунты оценивались при их использовании (как в случае с оператором cout), то если бы значение ньютонов изменилось, то и значение фунтов также изменилось бы.Поскольку фунты — это не указатель, а простое целое число, это невозможно.

А как насчет пошагового выполнения кода в отладчике?

В IME нет ничего подобного, чтобы понять выполнение программы, написанной на процедурном языке (т. е. смоделированной на основе того, как процессор фактически выполняет код).

Вы пытаетесь заставить слушателя подвергнуться смене парадигмы - полностью изменить свой подход к пониманию этого кода.

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

Может показаться немного странным очеловечивать блок памяти.:-)

Возьмем немного более сложный пример, где переменная типа newtons используется повторно и ему присваиваются значения более одного раза.Например:

double pounds, newtons;

newtons = 10.0;
pounds = newtons/NEWTONS_PER_POUND;
cout << pounds << endl;

newtons = 15.0;
pounds = newtons/NEWTONS_PER_POUND;
cout << pounds << endl;

return 0;

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top