类声明大括号后的分号

Posted

技术标签:

【中文标题】类声明大括号后的分号【英文标题】: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。根据您的建议编辑问题。 【参考方案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

【讨论】:

以上是关于类声明大括号后的分号的主要内容,如果未能解决你的问题,请参考以下文章

为什么golang的for循环后的大括号必须跟在for关键字后面

html中的大括号和百分号是啥意思?

Java中大括号的作用是啥?

Java - 我的分号和大括号上的随机错误

C语言语法错误 : “”咋解决?

es6解构中括号前加分号