Kar*_*aru 38 c++ language-design operators scope-resolution
(我知道范围解析运算符的作用,以及如何以及何时使用它.)
为什么C++有::运算符,而不是.为此目的使用运算符?Java没有单独的运算符,并且工作正常.C++和Java之间是否有一些区别,这意味着C++需要一个单独的运算符才能进行解析?
我唯一的猜测是::出于优先原因需要,但我不能认为为什么它需要具有比例如更高的优先级..我能想到的唯一情况就是如此
a.b::c;
Run Code Online (Sandbox Code Playgroud)
将被解析为
a.(b::c);
Run Code Online (Sandbox Code Playgroud)
,但我无法想到任何情况下,这样的语法无论如何都是合法的.
也许这只是"他们做不同的事情,所以他们可能看起来不同"的情况.但这并不能解释为什么::优先级高于..
Nic*_*las 31
因为C++标准委员会中有人认为允许此代码工作是个好主意:
struct foo
{
int blah;
};
struct thingy
{
int data;
};
struct bar : public foo
{
thingy foo;
};
int main()
{
bar test;
test.foo.data = 5;
test.foo::blah = 10;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
基本上,它允许成员变量和派生类类型具有相同的名称.当他们认为这很重要时,我不知道有人在吸烟.但它确实如此.
当编译器看到时.,它知道左边的东西必须是一个对象.当它看到时::,它必须是一个typename或命名空间(或者什么都没有,表示全局命名空间).这就是解决这种模糊性的方法.
Naw*_*waz 29
为什么C++不使用.它所使用的位置::,因为这是语言的定义方式.一个可能的原因可能是,使用::a如下所示的语法引用全局命名空间:
int a = 10;
namespace M
{
int a = 20;
namespace N
{
int a = 30;
void f()
{
int x = a; //a refers to the name inside N, same as M::N::a
int y = M::a; //M::a refers to the name inside M
int z = ::a; //::a refers to the name in the global namespace
std::cout<< x <<","<< y <<","<< z <<std::endl; //30,20,10
}
}
}
Run Code Online (Sandbox Code Playgroud)
我不知道Java如何解决这个问题.我甚至不知道在Java中是否存在全局命名空间.在C#中,您使用语法引用全局名称global::a,这意味着即使C#也有::运算符.
但是我无法想到这样的语法无论如何都是合法的.
谁说语法a.b::c不合法?
考虑这些类:
struct A
{
void f() { std::cout << "A::f()" << std::endl; }
};
struct B : A
{
void f(int) { std::cout << "B::f(int)" << std::endl; }
};
Run Code Online (Sandbox Code Playgroud)
现在看到这个(ideone):
B b;
b.f(10); //ok
b.f(); //error - as the function is hidden
Run Code Online (Sandbox Code Playgroud)
b.f() 不能这样调用,因为函数是隐藏的,GCC给出了这个错误信息:
error: no matching function for call to ‘B::f()’
Run Code Online (Sandbox Code Playgroud)
为了调用b.f()(或更确切地说A::f()),您需要范围解析运算符:
b.A::f(); //ok - explicitly selecting the hidden function using scope resolution
Run Code Online (Sandbox Code Playgroud)
与Java不同,C++具有多重继承.这是一个例子,你所讨论的那种范围分辨率变得很重要:
#include <iostream>
using namespace std;
struct a
{
int x;
};
struct b
{
int x;
};
struct c : public a, public b
{
::a a;
::b b;
};
int main() {
c v;
v.a::x = 5;
v.a.x = 55;
v.b::x = 6;
v.b.x = 66;
cout << v.a::x << " " << v.b::x << endl;
cout << v.a.x << " " << v.b.x << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么C++有::运算符,而不是使用.为此目的的运营商?
原因是Stroustrup本人给出的:
在C with Classes中,使用点来表示类的成员资格以及表达对特定对象的成员的选择.
这是造成一些轻微混淆的原因,也可用于构建含糊不清的例子.为了缓解这一点,
::引入了表示类的成员资格并且.仅为对象的成员资格保留
(Bjarne Stroustrup C++历史:1979-1991第21页 - 第3.3.1节)
而且这是真的
他们做不同的事情,所以他们可能看起来不同
确实
在
N::m既不N也不m是具有值的表达式;N并且m是编译器已知的名称并::执行(编译时)范围解析而不是表达式求值.可以想象允许重载x :: y,其中x是对象而不是命名空间或类,但这与首次出现相反 - 涉及引入新语法(允许expr::expr).这种并发症会带来什么好处并不明显.操作员
.(点)原则上可以使用与用于的相同技术来重载->.
(Bjarne Stroustrup的C++风格和技巧常见问题解答)