以下是否等同于正向声明?

Is the following equivalent to a forward declaration?

提问人:Luchian Grigore 提问时间:2/5/2012 最后编辑:CommunityLuchian Grigore 更新时间:2/5/2012 访问量:192

问:

这与最近的一个问题有关。

基本上是以下代码:

class A
{
    class B* b;
    B* c;
};

编译,尽管未声明或转发。此语法是否等同于正向声明?有什么区别吗?class B

C++ 转发声明

评论

0赞 CB Bailey 2/5/2012
我看不出这与您链接到的问题有何根本不同:指向尚未声明的结构的指针
2赞 j_random_hacker 2/5/2012
@CharlesBailey:嗯,这个问题是C++,而不是 C,C++往往对要求前向声明更挑剔(例如,链接问题中的代码片段不会在 C++ 中编译)。
1赞 CB Bailey 2/5/2012
@j_random_hacker:很好的指针,没有注意到链接问题中的“C”,但为什么链接的问题没有编译为C++?对我和.g++ -std=c++98 -pedantic
0赞 2/5/2012
是的,链接的问题是有效的 C++。C++ 的不同之处在于,由于类不共享单个命名空间,因此确定类声明引用哪个命名空间的规则可能有点复杂。
0赞 j_random_hacker 2/5/2012
你说得对@CharlesBailey,链接的问题确实很好C++!我的错误。我对这些问题之间差异的新解释:这个问题(与链接的问题不同)是询问当前瞻性声明采取定义的形式时,它是否具有或应该具有“持久效果”(即允许未来的定义在没有书面的情况下起作用),就像这里一样。Bclass

答:

1赞 Mr Lister 2/5/2012 #1

不,它是一个声明,指向 B 的指针。你在这里没有声明 B,只是一个指向它的指针,没有任何关于它的前进。

编辑:我错了,对不起。请参阅其他答案。

评论

2赞 2/5/2012
如果这没有声明,您如何解释在第 3 行没有收到错误,其中省略了关键字?Bclass
0赞 Luchian Grigore 2/5/2012
@hvd很好的回复,这实际上是我宣布成员的原因。c
0赞 Mr Lister 2/5/2012
对不起。但现在我看到有人对我的答案投了赞成票,即使它显然是错误的。是谁干的?
9赞 CB Bailey 2/5/2012 #2

可以在同一声明中声明类型和对象。

class B* b;

声明一个类型,以及一个类型指针指向 的对象。该类型不完整,并在它发生的作用域中查找,如果查找未能找到该类的现有声明,则该类型将在最近的封闭命名空间作用域(严格来说是非类非函数原型作用域,通常是命名空间)中命名一个类型。该对象是声明所在的范围的成员(在本例中为 )。BbBclass A

在大多数情况下,将完整类型和对象一起声明更为常见,在这种情况下,类型有时是匿名的。例如

struct { int a; int b; } x;

名称范围规则标准的相关部分是 7.1.5.3 [dcl.type.elab] 详细阐述的类型说明符 / 2 以及 3.4.4 和 3.3.1 中的引用部分:

3.4.4 描述了如何在精心设计的类型说明符中对标识符进行名称查找。如果标识符解析为名或枚举名,则 elaborated-type-specifier 将其引入声明,就像 simple-type-specifier 引入其类型名一样。如果标识符解析为 typedef-name 或模板类型参数,则 elaborated-type-specifier 格式不正确。[ ... ]如果名称查找未找到名称的声明,则 elaborated-type-specifier 的格式不正确,除非它是简单形式的类键标识符,在这种情况下,标识符按照 3.3.1 中所述进行声明。

评论

0赞 2/5/2012
这有点不准确,我认为:不是 的成员,但指的是 并且甚至在定义之外。BA::BA
0赞 2/5/2012
尽管如果另一个已经在范围内,例如由不超过 组成的声明,那么它可以引用嵌套类。Bclass B;A::B
0赞 2/5/2012
它实际上是最接近的非类非函数原型范围,这无关紧要,但请考虑:)void f() { struct s { struct p *ptr; } s; struct p { } p; s.ptr = &p; }
1赞 LihO 2/5/2012 #3

I would like to add few details to answer of Charles Bailey:

class A
{
public:
    class B * b;
    class C {} *c;
    int d;
} a;

B* globalB;
// C* globalC;  identifier "C" is undefined here

int main(int argc, char *argv[])
{
    a.d = 1;
    cout << a.d;
}

Yes, it defines incomplete type and as a pointer to at once. But here comes the fun:
"An exception to the scope visibility of a nested class declaration is when a type name is declared together with a forward declaration. In this case, the class name declared by the forward declaration is visible outside the enclosing class, with its scope defined to be the smallest enclosing non-class scope." (Nested Class Declarations
BbB)

Which means that type is defined out of scope which allows you to define variable . If you don't want to be defined out of scope , you can use just like it is used with type in my example.BAglobalBBA{}C

By the way, this example is correct and its output is: 1

评论

0赞 Luchian Grigore 2/5/2012
I actually tested the exact same thing after asking the question.