A melhor maneira de explicar declarativa falácia em C++?
-
20-09-2019 - |
Pergunta
Como pode um ofício, uma boa explicação de por que o seguinte código não está correto, em que o autor está a tentar escrever código C++ de forma declarativa, ao invés de incluir processualmente?
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;
}
O autor esperava cout
para exibir um cálculo apropriado, mas, em vez disso, recebe um "número louco."
Gostaria de explicar isso como "C++ é processual, e, portanto, ao tempo da declaração
pounds = newtons/NEWTONS_PER_POUND;
newtons
não foi atribuído um valor.
Alguma sugestão melhor?Ou uma explicação por que C++ não é "inteligente" o suficiente para realizar o comportamento do usuário por engano esperado?
Solução
Diga ao autor que
pounds = newtons/NEWTONS_PER_POUND;
comanda a CPU para
- Pegue o valor no endereço referido como "Newtons"
- Pegue o valor no endereço referido como "newtons_per_pound"
- Divida -os
- Armazene o resultado no endereço chamado de "libras"
O que ele está procurando é provavelmente uma função em termos imperativos:
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;
Outras dicas
O C++ é uma linguagem imperativa, não uma equação do solver.
C++ executa instruções na ordem em que você as escreve.C++ não inicializa variáveis, a menos que seja instruído para tal.C++ permite que você use uma variável cujo valor não foi inicializada, mas quando você fizer isso, o resultado é não especificado.Não especificado significa que qualquer coisa pode acontecer, inclusive as coisas ruins como a produção de "louco números".
Aqui está a explicação detalhada:
double pounds, newtons;
pounds = newtons/NEWTONS_PER_POUND;
newtons = 10.0;
A primeira instrução declara duas variáveis sem inicializá-los.Neste ponto, seus valores não especificados.
A segunda instrução lê o valor de newtons
(que poderia ser qualquer coisa) e divide-lo por NEWTONS_PER_POUND
.O resultado (que pode ser qualquer coisa) é atribuído a pounds
.
A terceira instrução inicializa newtons
, mas é tarde demais para afetar o cálculo de nós realizada.
Bem, isso não deve ser muito difícil de explicar, independentemente dos antecedentes dos alunos: apenas os que C ++ avaliam programas uma etapa de cada vez, declaração após declaração (apesar dos artefatos do compilador como reordenar…).
Não há absolutamente nada de especial para o C ++ '' de lidar com isso, nem é limitado à programação de computadores - é uma maneira cotidiana de lidar com uma lista ordenada de instruções.
Não é preguiçoso avaliar Newtons
Como tal, o cálculo é realizado no momento da declaração, não no momento da solicitação. Ele está após o código funcional, não o que o C ++ fará.
Se a pessoa não for excessivamente técnica, você pode tentar:
"As declarações deste programa C ++ são como as etapas necessárias para fazer um bolo. Você deve executar as etapas uma a uma e elas devem ser executadas em uma certa ordem para que seja um sucesso".
Explique que as libras recebem um valor na linha com o operador de atribuição:
pounds = newtons/NEWTONS_PER_POUND;
Se não fosse esse o caso, mas que a libra foi avaliada quando foi usada (como na instrução Cout), se o valor de Newtons mudou, o valor dos libras também mudaria. Como libras não é nenhum tipo de ponteiro, mas é um número inteiro simples, isso não é possível.
Que tal passar pelo código em um depurador?
IME não há nada assim para entender a execução de um programa escrito em um idioma processual (ou seja, modelado sobre como a CPU realmente executa o código).
Você está tentando fazer com que o ouvinte sofra uma mudança de paradigma - para alterar toda a sua abordagem para compreender esse código.
"libras" é apenas um número. Não tem nenhum conceito de como é criado. Você diz a "libras" como é criado, não se lembra. Ele apenas se lembrará do que é, não como é criado.
Pode parecer um pouco estranho para antropomorfizar um bloco de memória. :-)
Tome um exemplo um pouco mais complexo, onde uma variável como newtons
é reutilizado e atribuído valores mais de uma vez. Por exemplo:
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;
Mostre a ele o código e a saída. Em seguida, peça a ele para explicar como e por que o programa produz um número diferente para cada linha. Eu acho que isso deveria ajudar a empurrá -lo na direção de ver o programa como um procedimento que corre de cima para baixo.