What does the scope resolution operator return in the case of Type :: var?
It is, in fact, an lvalue. [expr.prim.id.qual] / 2 :
A nested qualifier name denoting a class [...] followed by the name of a member of that class ([class.mem]) or one of its base classes is a qualified identifier [...]. The result is a member. Result type - element type. The result is an lvalue if the member is a static member function or data member, and a prvalue otherwise.
Although its use outside of a class member access expression is severely restricted [expr.prim.id] / 2 , it can be used, in particular, in non-evaluated operands, where its lvalueness may appear:
struct A {
int x;
};
void f(int &);
using p = decltype(&(A::x)); // p is int*; the parens prevents forming a pointer-to-member
using q = decltype(f(A::x)); // q is void
source to share
A::x
is just a less ambiguous way of referring to a member x
, which may be needed if the local context shadows that member:
Example 1:
The child class also has a member x
.
struct B : public A
{
int x;
void foo()
{
int local_x = x;
int parent_x = A::x;
}
}
which will compile if you did x
protected
in the class A
(currently private
).
Example 2:
You can even use it in a member function A
that has x
as a parameter:
class A {
int x;
void foo(int x)
{
int parameter_x = x;
int member_x = A::x;
}
};
source to share
From C ++ Standard (5.1 Primary Expressions)
9 A nested qualifier name designating a class, optionally followed by a keyword template (14.2), followed by the name of a member of either that class (9.2) or one of its base classes (clause 10), is a qualified identifier; 3.4.3.1 describes name lookups for class members that appear in qualified identifiers. The result is a member. The type of the result is the type of the member. The result is an lvalue if the member is a static member function or data member, and a prvalue otherwise. [Note: A class member can refer to the use of a qualified identifier at any point in its potential scope (3.3.7). -end note] ...
A qualified name allows you to specify an otherwise hidden name, for example, when derived and base classes have members with the same name. for example
#include <iostream>
struct A
{
int i;
};
struct B : A
{
B( int i ) : A { i }, i( 2 * A::i ) {}
int i;
std::ostream &out( std::ostream &os = std::cout ) const
{
return os << "A::i = " << A::i << ", B::i = " << B::i;
}
};
int main()
{
B( 10 ).out() << std::endl;
return 0;
}
Program output
A::i = 10, B::i = 20
See also (5.1 Primary Expressions)
13 An identifier that denotes a non-static data member or non-static function of a class member can only be used:
(13.1) - as part of a member access of a class (5.2.5) in which an object expression refers to members of a class63 or a class derived from that class, or
(13.2) - to form a pointer to an element (5.3.1) or
(13.3) - if this id-expression denotes a non-static data member and it appears in an unpublished operand.
source to share
A::x
is the exact equivalent of static variable access in JAVA.
Regarding your example: -
1) x will be variable for different objects
2) A :: x will be a variable for the class itself. No matter how many objects from A were declared for each object, the value A::x
will be the same prior to assignment.
For example: -
#include<iostream>
using namespace std;
class A {
public:
static int x;
};
int A::x;
int main()
{
A a,b;
a.x=8;
b.x=6;
A::x=10;
return 0;
}
source to share