【问题标题】:Semicolon after class declaration braces类声明大括号后的分号
【发布时间】:2010-10-21 14:30:06
【问题描述】:

在 C++ 类中,为什么要在右大括号后面加上分号?我经常忘记它并得到编译器错误,因此浪费了时间。对我来说似乎有些多余,这不太可能。人们真的会做这样的事情吗:

class MyClass
{
.
.
.
} MyInstance;

我从结构和枚举的 C 兼容性的角度得到它,但由于类不是 C 语言的一部分,我猜它主要是为了保持相似声明构造之间的一致性。

我所寻找的更多是与设计原理相关,而不是能够改变任何东西,尽管一个好的代码完成 IDE 可能会在编译之前捕获这一点。

【问题讨论】:

  • 这可能会有所帮助:cpptalk.net/…
  • @Michael,感谢您的链接。从历史的角度来看,这很有意义,如果 C++ 允许所有 C 语法,并且 C++ 类与结构同义,那么我们在类的末尾留下了必要的分号。
  • @Brian,是的,严肃的问题。我很清楚我必须忍受它,但我对设计和实施背后的基本原理感到好奇。
  • 好的,但您也许应该编辑您的问题以包含您想要的设计原理。事实上,它鼓励人们提出诸如“为什么要使用花括号”之类的问题? :) 您可能有兴趣阅读 Stroustrup 的 Design & Evolution of C++,尽管它比课程末尾的分号更重要。
  • @Brian,很公平,关于是否将其 wiki 上的界限。在大型构建中经常使用的标题中省略了分号后提出了这个问题。我花了半个小时,因此参观了SO。根据您的建议编辑问题。

标签: c++ class oop declaration


【解决方案1】:

@MichaelHaren 提供的link 似乎提供了根本原因。分号(正如其他人指出的那样)是从 C 继承的。但这并不能解释为什么 C 首先使用它。讨论包括一个例子的宝石:

struct fred { int x; long y; }; 
main() 
{ 
  return 0; 
} 

除非另有声明,否则旧版本的 C 具有来自函数的隐式 int 返回类型。如果我们在结构定义的末尾省略;,我们不仅定义了一个新类型fred,而且还声明main() 将返回一个fred 的实例。 IE。代码会这样解析:

struct fred { int x; long y; } main()
{ 
  return 0; /* invalid return type, expected fred type */
} 

【讨论】:

  • 是的,隐式 int 返回类型会影响这里的所有内容。不错的宝石
【解决方案2】:

类型声明中右大括号后的分号是该语言所必需的。从最早的 C 版本开始就是这样。

是的,人们确实会执行您刚刚发布的声明。它对于在方法内部创建作用域类型很有用。

void Example() {
  struct { int x; } s1;
  s1.x = 42;

  struct ADifferentType { int x; };
}

在这种情况下,我认为很清楚为什么需要分号。至于为什么在头文件中声明的更一般情况下需要它,我不确定。我的 猜测 是它具有历史意义,并且这样做是为了使编写编译器更容易。

【讨论】:

  • 为什么我不能只创建作用域类型而不指定 MyInstance?当你结合两个动作时,它看起来很奇怪:声明新类型和声明新变量。
  • @Mykola 你可以两者兼得。查看我添加的示例
【解决方案3】:

我猜这是因为类是声明,即使它们需要大括号进行分组。是的,有一个历史论点,因为在 C 中你可以这样做

struct
{
  float x;
  float y;
} point;

您应该在 C++ 中能够做类似的事情,class 声明以相同的方式运行是有意义的。

【讨论】:

    【解决方案4】:

    简称

    class MyClass
    {
    .
    .
    .
    };
    
    // instance declaration
    MyClass MyInstance;  // semicolon here
    

    类声明的花括号后面的分号实际上是多余的,但它是 C++ 的定义方式。变量声明后的分号总是需要的,而且是有意义的。

    【讨论】:

    • 那么,C++ 是否需要在每个声明后使用分号?
    • 请注意,这种方式不能创建匿名类的对象,而其他方式可以。
    【解决方案5】:

    我不使用这样的声明

    class MyClass
    {
    .
    .
    .
    } MyInstance;
    

    但在这种情况下,我可以理解为什么会有分号。
    因为它就像int a; - 变量声明。

    可能是为了保持一致性,因为您可以省略“MyInstance”分号。

    【讨论】:

      【解决方案6】:

      出于兼容性原因,在struct 之后需要它,您希望这样:

      struct MyStruct { ... };
      class  MyClass  { ... }    //inconsistency
      

      【讨论】:

      • 但是namespace myNamespace { ... } // inconsistent but valid呢?
      【解决方案7】:

      在 C/C++ 中 ;是语句终止符。 所有语句都以 ; 结尾避免歧义(并简化解析)。 语法在这方面是一致的。 即使一个类声明(或任何块) 是多行长并且是 用 {} 分隔它仍然只是一个语句({ } 是语句的一部分) 因此需要用 ; 终止(; 不是分隔符/定界符)

      在你的例子中

      class MyClass{...} MyInstance;
      

      是完整的语句。 可以在单个语句中定义声明类的多个实例

      class MyClass{...} MyInstance1, MyInstance2;
      

      这与在单个语句中声明原始类型的多个实例完全一致:

      int a, b, c;
      

      之所以不经常看到这样的类和实例声明,是因为实例只能?是一个全局变量,除非它们是静态和/或普通旧数据结构,否则您并不经常需要全局对象。

      【讨论】:

      • 但是函数定义也是一个语句,但是没有分号。
      【解决方案8】:

      我们可以定义一个class something {...}accum, trans;,其中accum 和trans 可以是something 类的两个对象。因此,为了声明类的对象,我们在类之后使用semi-colon

      【讨论】:

        猜你喜欢
        • 2011-02-01
        • 1970-01-01
        • 2012-11-26
        • 1970-01-01
        • 2016-12-26
        • 2021-10-17
        • 1970-01-01
        • 1970-01-01
        • 2020-03-28
        相关资源
        最近更新 更多