当出现Injected-Class-Name时会发生什么?(C++)

4
根据https://en.cppreference.com/w/cpp/language/injected-class-name,在类作用域中,当前类的名称被视为公共成员名称;这被称为注入类名。名称的声明点紧随类定义的左花括号之后。
int X;
struct X {
    void f() {
        X* p; // OK. X refers to the injected-class-name
        ::X* q; // Error: name lookup finds a variable name, which hides the struct name
    }
};

那么代码中实际发生了什么?X* p 是否会变成 X::X* p

2个回答

6
那么代码究竟发生了什么?X* p 被转换为 X::X* p 了吗?基本上是这样的。名称查找规则始于最窄的作用域。当您在 f 中执行 X* p; 时,它会在 f 的作用域中查找并且找不到任何内容。然后它检查 X 的作用域,因为 f 被限定为 X。它发现 X,因为它被注入到类作用域中,所以停止查找并获得类类型。当你做 ::X* q; 然后 ::X 表示在全局命名空间中查找 X,但只能找到一个变量,而不是类型,所以会出现错误。

因此,像 X::X::foo 这样的东西会出现的原因(类似于:https://dev59.com/lFYN5IYBdhLWcg3w2rSU?noredirect=1&lq=1)是因为 Injected-Class-Name 忽略了那些作用域查找,只是简单地使用 X::foo? - csguy
@csguy 当你创建一个类时,编译器会将类名变为类的成员。因此,class_name::class_name总是有效的,因为class_name::class_name就是class_name,你可以再次访问它的成员变量,一直这样继续下去,如X::X::X::X::X::X::X::X::X::X::X::X::f();(如果你真的想这样做)。 - NathanOliver
那是因为注入的类名,对吧? - csguy
1
是的。如果没有注入名称,则“class_name :: class_name”将无效(构造函数不可访问)。 - NathanOliver
1
@csguy 是的。C++ 不是挺有趣的吗? ;) - NathanOliver
显示剩余3条评论

4

这个限定名::X在全局命名空间中进行搜索。由于没有这样一个名称的类型(变量声明隐藏了类型struct X),编译器会发出错误。

你可以使用一个详细的名称,例如

int X;
struct X {
    void f() {
        X* p; // OK. X refers to the injected-class-name
        struct ::X* q; // OK. elaborated name struct ::X
    }
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接