class 定义后是否允许使用 class 声明?
Is a class declaration allowed after a class definition?
刚看完this answer,完全不解。
我一直在想一个class声明可以出现很多次,而定义只需要存在一次,比如:
/*class Class {*/
class A; // (1) forward declaration
class A { // (2) definition, only once
int m;
};
class A; // (3) declaration again, legal?
class A a; // (4) declaration again, legal?
/*};*/
来自链接的答案:如果上面的代码 嵌套在 class 中,则 (3)(和 (4)?)是非法的(class A
的定义和声明嵌套在 class Class
中)。
在cppreference上找到了上面的例子,没有嵌套:
struct s { int a; };
struct s; // does nothing (s already defined in this scope)
void g() {
struct s; // forward declaration of a new, local struct "s"
// this hides global struct s until the end of this block
s* p; // pointer to local struct s
struct s { char* p; }; // definitions of the local struct s
}
见第二行。
问题:鉴于在class内部是非法的,是我的示例代码,以及上面的cppreference示例,当不是 嵌套在 class 中?或者更一般地说:class 声明什么时候可以跟在定义之后(例如,它在名称空间中是怎样的)?如果合法,为什么会有差异?
class A;
这是不完整的前向声明class A
(合法)。
class A { int m; };
这是Class A
的定义(合法)。
class A;
这是 class A
的重新声明(合法)。
class A a;
这是类型 A
(合法)的对象 a
的声明。
来自[basic.def]:
A declaration (Clause 7) may introduce one or more names into a translation unit or redeclare names introduced by previous declarations.
来自[class.name]:
A declaration consisting solely of class-key identifier; is either a redeclaration of the name in the current scope or a forward declaration of the identifier as a class name. It introduces the class name
into the current scope.
所以这样做通常是合法的。 [class.mem] 中只有一个例外:
A member shall not be declared twice in the member-specification,
except that a nested class or member class template can be declared and then later defined, and except that an enumeration can be introduced with an opaque-enum-declaration and later redeclared with an enum-specifier.
在命名空间范围内完全可以,在 class 范围内不允许。
至于为什么?好吧,这条规则让你 "forward" 在你通常被允许这样做的任何地方声明你需要的所有 classes:
// a.h
struct C;
struct A {
C* c;
};
// b.h
struct C;
struct B {
C& c;
};
无需担心有人实际包含完整声明并为您破坏一切:
// d.h
#include "c.h"
#include "a.h" // now C was already declared!
#include "b.h" // and here too!
struct D { ... };
在 class 定义 中,这并不是什么大问题。它不能完全跨越多个文件。因此,无法重新声明嵌套类型实际上并没有实现任何目标。
刚看完this answer,完全不解。
我一直在想一个class声明可以出现很多次,而定义只需要存在一次,比如:
/*class Class {*/
class A; // (1) forward declaration
class A { // (2) definition, only once
int m;
};
class A; // (3) declaration again, legal?
class A a; // (4) declaration again, legal?
/*};*/
来自链接的答案:如果上面的代码 嵌套在 class 中,则 (3)(和 (4)?)是非法的(class A
的定义和声明嵌套在 class Class
中)。
在cppreference上找到了上面的例子,没有嵌套:
struct s { int a; }; struct s; // does nothing (s already defined in this scope) void g() { struct s; // forward declaration of a new, local struct "s" // this hides global struct s until the end of this block s* p; // pointer to local struct s struct s { char* p; }; // definitions of the local struct s }
见第二行。
问题:鉴于在class内部是非法的,是我的示例代码,以及上面的cppreference示例,当不是 嵌套在 class 中?或者更一般地说:class 声明什么时候可以跟在定义之后(例如,它在名称空间中是怎样的)?如果合法,为什么会有差异?
class A;
这是不完整的前向声明class A
(合法)。
class A { int m; };
这是Class A
的定义(合法)。
class A;
这是 class A
的重新声明(合法)。
class A a;
这是类型 A
(合法)的对象 a
的声明。
来自[basic.def]:
A declaration (Clause 7) may introduce one or more names into a translation unit or redeclare names introduced by previous declarations.
来自[class.name]:
A declaration consisting solely of class-key identifier; is either a redeclaration of the name in the current scope or a forward declaration of the identifier as a class name. It introduces the class name into the current scope.
所以这样做通常是合法的。 [class.mem] 中只有一个例外:
A member shall not be declared twice in the member-specification, except that a nested class or member class template can be declared and then later defined, and except that an enumeration can be introduced with an opaque-enum-declaration and later redeclared with an enum-specifier.
在命名空间范围内完全可以,在 class 范围内不允许。
至于为什么?好吧,这条规则让你 "forward" 在你通常被允许这样做的任何地方声明你需要的所有 classes:
// a.h
struct C;
struct A {
C* c;
};
// b.h
struct C;
struct B {
C& c;
};
无需担心有人实际包含完整声明并为您破坏一切:
// d.h
#include "c.h"
#include "a.h" // now C was already declared!
#include "b.h" // and here too!
struct D { ... };
在 class 定义 中,这并不是什么大问题。它不能完全跨越多个文件。因此,无法重新声明嵌套类型实际上并没有实现任何目标。