为什么不能在没有花括号的情况下创建1语句函数?

时间:2014-09-15 11:23:10

标签: java c# c++

因此,在大多数编程语言中,如果使用循环或if,如果只有一个语句,则可以不使用花括号,例如:

if (true)
    //Single statement;

for (int i = 0; i < 10; i++)
    //Single Statement

while (true)
    //Single statement

但是,它不适用于函数,例如:

void myFunction()
    //Single Statement

所以,我的问题,为什么它不能用于函数?

8 个答案:

答案 0 :(得分:8)

C ++需要它来消除一些结构的歧义:

void Foo::bar() const int i = 5;

const现在属于bar还是i

答案 1 :(得分:5)

因为语言语法禁止你这样做。

Java语法定义了如下方法:

MethodDeclaration:
    MethodHeader MethodBody

Methodbody as:

MethodBody:
    Block 
    ;

这意味着Block(见下文)或单个分号

Block:
    { BlockStatementsopt }

一个块作为大括号内的一个或多个语句。

但if定义为:

IfThenStatement:
    if ( Expression ) Statement

在结束后不需要阻止的情况下,因此单行就可以了。

为什么他们选择这样定义?人们只能猜测。

语法可以在这里找到:http://docs.oracle.com/javase/specs/jls/se7/html/index.html

答案 2 :(得分:4)

这不是一个规则,在某些语言中你可以(Python?是的,我知道这是一个非常人为的例子:))),在其他语言中你不能。

您可以很好地将问题扩展到类和名称空间,例如,为什么不:

namespace Example
    class Foo : public Bar
        public: std::string myMethod()
            return "Oh noes!";

正确?在每个级别,这只是一个项目,那么为什么不到处跳过括号?

答案同时又简单而复杂。

简单来说,它是关于可读性的。请记住,您可以根据需要布置代码,,因为编译器通常会丢弃空格

namespace Example class Foo : public Bar public: std::string myMethod() return "Oh noes!";

嗯,开始看起来难以理解。请注意,如果您添加大括号

namespace Example { class Foo : public Bar { public: std::string myMethod() {return "Oh noes!";}}}
奇怪的是,它变得有些可理解。

实际问题不是可读性(无论如何关心?我当然是在开玩笑)但在后者:理解。您不仅必须能够理解代码 - 编译器必须。对于编译器来说,没有&#34;哦,这看起来像函数&#34;。编译器必须绝对确定它是一个函数。此外,它必须完全确定它的起始位置,结束位置,等等。而且必须这样做而不要过多地查看空格,因为C系列语言允许您以任意数量添加它们。

所以,让我们再看看打包的无支撑示例

namespace Example class Foo : public Bar public : std::string myMethod() return "Oh noes!";
                            ^                   ^    ^^

我标记了一些有问题的符号。假设你可以定义一个处理它的语法,请注意&#34;的含义:&#34;性格变化。有一段时间它表示你正在指定继承,另一方面它指定了一个方法的访问修饰符,在第三方面它只是命名空间限定符。好吧,如果你很聪明,可以放弃第三个,并注意到它实际上是&#39; ::&#39;符号,而不只是&#39;:&#39;字符。

此外,关键字的含义可能会发生变化:

namespace Example class Foo : public Bar public : std::string myMethod() return "Oh noes!";
                              ^^^^^^     ^^^^^^

首先,它为继承的基类定义访问修饰符,在第二个位置定义了方法的访问修饰符。更重要的是,首先它的并不意味着后面跟着&#34;:&#34;在第二个地方,它必须被它跟随!

如此多的规则,例外和极端案例,我们只涉及两个简单的事情:公共和&#39;:&#39;。现在,想象一下你要指定整个语言的语法。你用你想要的方式描述一切。但是,当你将所有规则收集在一起时,它们在某些时候可能会重叠并相互碰撞。添加第N个规则后,可能会发生您的编译器&#39;我们无法判断公众是否会这样做。实际上标记了继承,或者启动了一个方法:

namespace Example class Foo : public ::Bar public : std::string myMethod() return "Oh noes!";
                              ^^^^^^^^     ^^^^^^^^

请注意,我只将Bar更改为::Bar。我只添加了一个命名空间限定符,现在我们的&#34; public的规则之后是冒号&#34;被摧毁了。由于我现在添加了一个规则,即&#34;基类名称可能具有命名空间限定符&#34;,我还必须添加更多规则来覆盖另一个极端情况 - 消除&#34; public&#34含义的模糊性;和&#34;:&#34;在这个地方。

减少冗长的话题:规则越多,问题越多。 &#34;编译器&#34;成长,变慢,吃更多的资源来工作。这导致无法处理大型代码文件,或者当用户必须等待该模块进行编译时才会感到沮丧。

但对于用户来说更糟糕的是,更糟糕的错误消息越复杂或越模糊。没有人想使用无法解析某些代码的编译器,也无法告诉你它有什么问题。

请记住,在C ++中,当你忘记了一些&#39 ;;&#39;在.h文件中?或者当你忘记一些}时?编译器报告错误30或300行更远。这是因为&#39 ;;&#39;和&#39; {}&#39;可以在许多地方省略,对于30或300行,编译器根本不知道错误!如果在任何地方都需要括号,可以更快地确定错误点。

另一种方式:在命名空间,类或函数级别使它们可选,将删除基本的块开始/块结束标记,至少:

  • 可能会使语法模糊不清(因此强制添加更多规则)
  • 可能会损害检测(和报告!)错误

任何人都不想要的任何部分。

C ++语法非常复杂,实际上根本不可能省略那些地方的大括号。对于Java或普通的C,我认为可以创建一个不需要它们的语法/编译器,但是它仍然会损害错误报告。特别是在允许使用#include和宏的C中。在早期的Java中,影响可能会更小,因为语法相对简单,比较当前的C ++ ..

可能最简单,最快速,最容易实现,也许最容易学习的语法......需要几乎无处不在的大括号(或任何其他分隔符)。例如,检查LISP。但是,你的大部分工作将包括不断编写相同的必需标记,许多语言用户根本不喜欢(即当我需要在VisualBasic中使用&#34处理一些旧代码时,我会感到恶心;如果然后结束,如果&#34; yuck)

现在,如果你看一下像Python这样的无支撑语言 - 他们如何解决它?它们通过......意图来表示块开始/块结束。使用此语言,您必须正确缩进代码。如果你没有正确地缩进它,它根本就不会编译,或者循环/函数/等会默默地让它们的代码弄乱,因为编译器不会知道哪个部分属于哪个范围。再没有免费午餐。

答案 3 :(得分:1)

基本上,方法(函数)是一组语句,它们组合在一起以执行操作。我们将语句分组为可重用的。也就是说,如果您知道在这种情况下将经常使用一组指令,我们将其创建为单独的函数。

如果您可以在一行代码中执行任务,那么为什么需要编写函数?

答案 4 :(得分:0)

没有理由在编译器中添加额外的解析代码,因为功能真的没用,你编写了多少个不是访问器或者mutator的一行方法?这已在C#中通过属性处理,但尚未在Java中处理。

所以原因是,考虑到大多数开发人员不鼓励遗漏可选的支架块,它不太可能被使用。

答案 5 :(得分:0)

因为语言的语法不允许你这样做。

以下是取自ISO / IEC 9899-1999规范的C函数的语法:

6.9.1 Function definitions
Syntax
1     function-definition:
          declaration-specifiers declarator declaration-listopt compound-statement

复合语句部分是函数体,复合语句声明为

compound-statement:
    { block-item-listopt }

即。它以大括号开始和结束。

ifwhile或类似机构的身体可以statement

 (6.8.5) iteration-statement:
             while ( expression ) statement

声明可以是几种结构之一。

statement:
    labeled-statement
    compound-statement
    expression-statement
    selection-statement
    iteration-statement
    jump-statement

其中只有compound-statement需要大括号。

答案 6 :(得分:0)

你无法准确地说C#中没有一个语句功能。匿名方法可能就是其中之一。如果没有单行语句,我们就无法在c#中使用Lambda表达式。 C#3.0不会存在。

答案 7 :(得分:0)

在c ++中,你需要一个复合语句来创建一个函数体 - 它实际上是用花键围绕的。这并不意味着你需要立即拥有大括号,下面将编译得很好:

int foobar()
    try {
      return 1;
    }
    catch (...){return 0;}