作用域解析操作符的作用是什么



我最近遇到了一个问题:当点运算符(.(的用法与前者不冲突时,为什么还要使用

范围解析运算符比如

namespace my_module
{
const int insane_constant = 69;
int some_threshold = 100;
}

为了访问some_threshold,可以写入my_module::some_threshold。但问题是,据我所知,::的左手边必须是一个命名空间或类,而.的左手边永远不能是命名空间或类。此外,::的阶数高于.,这在我看来真的毫无意义。为什么让两个不同的操作符都不能重载,而用例只能由一个覆盖?我很难找到任何令人满意的答案,所以关于这件事的任何线索都很有价值。

考虑以下代码:

#include <iostream>
namespace my_module
{
const int insane_constant = 69;
}
class C{
public:
int insane_constant; // actually not constant, but for the example's sake
};
int main(){
C my_module;
my_module.insane_constant = my_module::insane_constant;
std::cout << my_module.insane_constant;
}

在这里,您将如何区分my_module.::0?

您不能用另一个替换一个
示例:

namespace A
{
int x = 0;
struct X { int x = 1; } A;
void f()
{
std::cout << A.x
<< A::x
<< std::endl;
}
}

int main()
{
A::f();
}

打印";10〃;。

两个运算符的目的完全不同。

特别地,::用于指代作用域成员,而operator.用于指代对象的<em]成员。>

也就是说,operator::处理作用域,而operator.处理对象。

例如,classname::membername是指具有与其相关联的类作用域的类的成员。另一方面,object.membername是指对象object的成员。

请注意,并非所有作用域都可以与operator::一起使用。例如,我们可以使用operator::来引用namespace scope的成员、class scopes' member(类似于静态成员等(、enumeration' member等。

其他答案展示了::.做不同事情的情况,因为它们作用于不同的实体(作用域与对象(。我想通过将它与C#中的情况进行比较,为语言中的这一选择添加一些动机。免责声明:我实际上并没有使用C#,但这些点在研究时似乎很明显。

在C#中;命名空间运算符";是一个点.,就像成员访问操作符一样。然而,你不可能有真正的全局变量:你需要一个类来放置它们。事实上,你甚至不能声明一个没有命名空间的类,尽管这与你的问题无关。

在C#中,当使用作用域和对象之间的点时,不存在可能的歧义。嵌套的名称空间、名称空间中的类、类静态变量、枚举器等等都是用句点访问的。

在C++中,情况显然并非如此,而且该语言通过使用两个不同的运算符来区分作用域和对象。

在纯C中,没有作用域解析,因此不需要::运算符。其他有区别的语言是Ruby,显然还有PHP。在没有区别的语言中,您可以找到例如Python、Go和Java。最后一个确实有一个::运算符,但它不是用于范围解析,而是用于形成方法引用。

简而言之,C++具有复杂的作用域机制,因为这就是该语言的设计方式。因此,它需要两个不同的运算符来区分作用域访问和对象访问。

最新更新