以下内容是否相当于前向声明?

发布于 2025-01-02 19:13:29 字数 274 浏览 3 评论 0原文

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

基本上是以下代码:

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

尽管 class B 未声明或前向声明,但仍可编译。此语法相当于前向声明吗?有什么区别吗?

This is related to a recent question.

Basically the following code:

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

compiles although class B is not declared or forward-declared. Is this syntax equivalent to a forward declaration? Are there any differences?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

撧情箌佬 2025-01-09 19:13:29

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

class B* b;

声明一个类型 B 和一个对象 b,该对象具有指向 B 的类型指针。该类型是不完整的,并且在它出现的范围中查找,如果查找未能找到该类的现有声明,则该类型在最近的封闭命名空间范围中命名一个类型(严格非类非函数原型)范围,通常是命名空间)。该对象是声明所在范围的成员(在本例中为class A)。

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

struct { int a; int b; } x;

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

3.4.4 描述了如何在详细类型说明符中对标识符进行名称查找。如果标识符解析为类名枚举名,则详细类型说明符引入它到声明中的方式与简单类型说明符引入其类型名称相同。如果标识符解析为typedef-name或模板类型参数,则详细类型说明符格式不正确。 [ ... ] 如果名称查找未找到该名称的声明,则详细类型说明符格式不正确,除非它是简单形式类键标识符 em> 在这种情况下,标识符按照 3.3.1 中的描述进行声明。

You can declare a type and an object in the same declaration.

class B* b;

Declares a type, B and an object b which has type pointer to B. The type is incomplete and is looked up in the scope in which it occurs, if the lookup fails to find an existing declaration for the class then the type names a type in the nearest enclosing namespace scope (strictly non-class non-function-prototype scope, which is usually a namespace). The object is a member of the scope in which the declaration appears (in this case, class A).

In most cases it's more common to declare a complete type and an object together, in this case the type is sometimes left anonymous. E.g.

struct { int a; int b; } x;

The relevant parts of the standard for the name scoping rules are 7.1.5.3 [dcl.type.elab] Elaborated type specifiers / 2 and the referenced sections in 3.4.4 and 3.3.1 :

3.4.4 describes how name lookup proceeds for the identifier in an elaborated-type-specifier. If the identifier resolves to a class-name or enum-name, the elaborated-type-specifier introduces it into the declaration the same way a simple-type-specifier introduces its type-name. If the identifier resolves to a typedef-name or a template type-parameter, the elaborated-type-specifier is ill-formed. [ ... ] If name lookup does not find a declaration for the name, the elaborated-type-specifier is ill-formed unless it is of the simple form class-key identifier in which case the identifier is declared as described in 3.3.1.

痴情换悲伤 2025-01-09 19:13:29

不,它是一个指向 B 的指针的声明。您在这里不是声明 B,只是指向它的指针,并且没有任何关于它的内容。

编辑:我错了,抱歉。参见其他答案。

No, it's a declaration, of a pointer to B. You are not declaring B here, only a pointer to it, and there's nothing forward about it.

Edit: I was wrong, sorry. See other answer.

自由如风 2025-01-09 19:13:29

我想添加一些细节来回答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;
}

是的,它定义了不完整的类型B< /code> 和 b 同时作为指向 B 的指针。但有趣的是:
“嵌套类声明的范围可见性的一个例外是当类型名称与前向声明一起声明时。在这种情况下,前向声明声明的类名在封闭类的外部是可见的,其范围定义为最小的封闭非类范围。” (嵌套类声明

这意味着类型 B 定义在 A 范围之外,它允许您定义变量 globalB。如果您不希望在 A 范围之外定义 B,则可以使用 {},就像与 类型一起使用一样在我的示例中为 >C

顺便说一下,这个例子是正确的,它的输出是:1

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 B and b as a pointer to B 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)

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文