【问题标题】:Best way to explain declarative fallacy in C++?在 C++ 中解释声明性谬误的最佳方法是什么?
【发布时间】:2009-09-01 06:42:50
【问题描述】:

如何才能很好地解释为什么以下代码不正确,因为作者试图以声明方式而不是程序方式编写 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++ 不够“智能”来执行用户错误预期的行为?

【问题讨论】:

  • 许多现代编译器会尝试识别未初始化的变量并将它们报告为编译时错误。
  • 实际上遵循您正在使用的语言的语义(并学习它们,如果您不了解它们)通常会有所帮助。没有人可以用 C++ 编写它并期望它以任何方式“工作”。也许它会,在一种虚构的 C++ 语言中,但不是在真实的语言中。如果他不明白你的解释,好吧,他只是太固执或心甘情愿地对现实视而不见。
  • 再一次,我认为人们必须首先学习低级语言......从汇编开始。在汇编中,计算机工作的固有顺序方式是显式的。
  • 没有b=c之类的混淆语句。
  • 它在一个 CPU 中。然后,一旦你开始研究一些 VHDL,它就不是了。

标签: c++ declarative procedural


【解决方案1】:

告诉作者

pounds = newtons/NEWTONS_PER_POUND;

命令 CPU 去

  • 在称为“牛顿”的地址处取值
  • 取名为“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;

【讨论】:

    【解决方案2】:

    C++ 是一种命令式编程语言,而不是方程求解器。

    C++ 按照您编写语句的顺序执行语句。除非被告知,否则 C++ 不会初始化变量。 C++ 允许您使用其值尚未初始化的变量,但是当您这样做时,结果是未指定。未指明意味着任何事情都可能发生,包括产生“疯狂数字”之类的坏事。

    下面是详细解释:

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

    第一条语句声明了两个变量,但没有初始化它们。此时,它们的值是未指定的。

    第二条语句读取newtons 的值(可以是任何值)并将其除以NEWTONS_PER_POUND。结果(可以是任何东西)分配给pounds

    第三条语句初始化newtons,但是来不及影响我们刚刚进行的计算。

    【讨论】:

    • "按照您编写的顺序执行语句。"这是不正确的。米(++x);。我首先“写”了m 的电话。但它实际上会先增加x,然后调用m
    • @silky: "m(++x);"是一个陈述。
    • 写的时候,希望大家充分了解优先顺序。因此,您已经按该顺序编写了它。否则,你不知道代码是做什么的,为什么还要写代码?
    • @Pod:你在说什么?我当然理解运算符优先级!但它与 >>>STATEMENTS
    • “C++ 是一种编程语言,而不是方程求解器。” 我猜你的意思是:“C++ 是一种过程编程语言,而不是一种声明性语言。”毕竟,有声明性编程语言允许相关代码工作。
    【解决方案3】:

    这不应该太难解释,不管学生的背景如何:只是告诉他们 C++ 一步一步地评估程序,一个语句接一个语句(尽管编译器工件,例如重新排序......)。

    C++ 的处理方式绝对没有什么特别之处,它甚至不仅限于计算机编程,而是一种处理有序指令列表的日常方式。

    【讨论】:

      【解决方案4】:

      评估牛顿并不懒

      因此,计算是在声明时执行的,而不是在请求时执行的。他追求的是功能代码,而不是 C++ 会做什么。

      【讨论】:

      • 如果他们是程序员,他们可能知道“懒惰评估”是什么意思。否则这会有点混乱。
      • 真的吗?我一直认为懒惰而不是渴望的解释是向非程序员解释的更容易的事情之一。懒惰,在需要时做,渴望,在被告知时做。
      • 在函数式编程中,还是要尊重程序流程的顺序。我认为作者的代码更倾向于逻辑(基于约束)编程。
      • @Spenced,我实际上已经向非程序员解释了我使用“惰性评估”构建的东西,他们对我使用技术术语感到恼火! “懒惰”本身是显而易见的,但懒惰的评估似乎需要更多解释。
      【解决方案5】:

      如果这个人不是太技术,你可以试试:

      “这个 C++ 程序中的语句就像做蛋糕所需的步骤。您必须逐个执行这些步骤,并且必须按照一定的顺序执行它们才能成功。”

      【讨论】:

      • 向“不太懂技术”的人解释 C++ 似乎没什么用 :)
      • @n0rd,你说得对,我可能应该说“一个没有经验的程序员”。
      【解决方案6】:

      用赋值运算符解释磅被赋值的行:

      pounds = newtons/NEWTONS_PER_POUND;
      

      如果不是这种情况,但磅在使用时被评估(与 cout 语句一样),那么如果牛顿的值发生变化,那么磅的值也会发生变化。由于磅不是任何类型的指针,而是一个简单的整数,所以这是不可能的。

      【讨论】:

        【解决方案7】:

        如何在调试器中单步执行代码?

        IME 没有这样的方法来理解用过程语言编写的程序的执行(即,以 CPU 实际执行代码的方式为模型)。

        【讨论】:

          【解决方案8】:

          您正试图让听众进行范式转变 - 改变他/她理解这段代码的整个方法。

          “磅”只是一个数字。它没有 它如何创建的概念。你告诉 “磅”它是如何创建的,它不会 记住。它只会记住什么 它是,而不是它是如何创建的。

          将一块记忆拟人化似乎有点奇怪。 :-)

          【讨论】:

          • 不要将计算机拟人化。他们讨厌那样。 ;-)
          【解决方案9】:

          举一个稍微复杂一点的例子,像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;
          

          向他展示代码和输出。然后请他解释程序如何以及为什么为每一行生成不同的数字。我认为这应该有助于推动他将程序视为从上到下运行的过程。

          【讨论】:

            猜你喜欢
            • 2016-05-19
            • 2023-03-03
            • 1970-01-01
            • 1970-01-01
            • 2011-01-29
            • 2011-01-12
            • 2011-12-01
            • 1970-01-01
            • 2011-11-01
            相关资源
            最近更新 更多