Originally Posted by
shivam1992
so its used to access static members from a class?
The scope resolution operator is about more than accessing static members of a class.
A namespace is a (named) scope. All names within the namespace belong in a scope with the same name as the namespace. Hence, to access something named x within a namespace named n, the syntax is n::x. Things that can be named include types, variables, and other scopes (so a namespace can be nested in a namespace,
The name of a struct or class type in C++ is also a scope, with the same name as the struct type. Any member of a struct or class type can therefore be accessed using the syntax struct_name::member_name in any setting where access of that member makes sense.
So, it is possible to use the scope resolution to access a static member of a class/struct
Code:
struct X
{
public:
static int foo;
};
int X::foo; // definition needed once and only once within a program
int main()
{
X::foo = 42; // changes the static member of X named foo.
}
Naturally, the assignment "X::foo = 42" above will not compile if foo is a private or protected member of X.
However, scope resolution can also be used to access non-static members of a struct or class. For example;
Code:
#include <iostream>
class Y
{
public:
Y() {};
virtual int Hello();
};
int Y::Hello() // note use of scope operator to implement Y's Hello()
{
return 42;
}
class Z : public Y
{
public:
Z() : Y() {};
int Hello();
};
int Z::Hello() // Note use of scope operator in definition of Z's Hello()
{
return 2*Y::Hello(); // Note use of scope operator to call Y's Hello()
}
int main()
{
Y *y = new Y;
Y *z = new Z;
std::cout << y->Hello() << '\n';
std::cout << z->Hello() << '\n';
std::cout << y->Y::Hello() << '\n';
std::cout << z->Y::Hello() << '\n'; // note that this does not call Z::Hello()
}
I mention the last line for completeness - it is rarely a good idea in practice: if a caller needs to force the compiler to call Y::Hello() rather than Z::Hello() for an object of type Z, then that is usually a sign of a class design problem.
There are limits to scope resolution. In the last code sample, for example, the line
Code:
std::cout << y->Z::Hello() << '\n';
would not compile, since y is of type Y, and it does not make sense to call Z::Hello().
Originally Posted by
shivam1992
or when using isnt specified? , why would it be used if the using directive isnt present?
This question shows you have got the idea of scope resolution completely backward. The scope resolution operator is not something that is used to avoid the "using" directive. The "using" directive is a flawed shortcut to reduce need to employ the scope resolution operator.
Every name is within some scope. And the complete name of a variable, x, within a scope s is s::x. Given the syntax s::x, the compiler has only two choices: it accesses the name x within scope s, or it reports an error (eg because scope s does not exist, or because scope s does not contain anything named x). There is such a thing as an unnamed namespace, so
Code:
int x;
int main()
{
x = 42;
::x = 50; // this affects the x above. The only difference is that we tell the compiler specifically to change the value of x in the global (unnamed) namespace
}
What the using directive does is tell the compiler how to search for candidate matches to unadorned names (such as x). For example;
Code:
namespace Junk
{
int x;
}
using namespace Junk;
int main()
{
x = 42;
}
The using directive tells the compiler that, if it sees a name, to look for a match in namespace Junk for a candidate match. There is no x in the global namespace (i.e. there is no ::x) so the assignment "x = 42" affects the variable Junk::x.
If the using namespace directive is removed, this code will not compile because the compiler is no longer being told to look within namespace Junk. The compiler does not match "x" to "Junk::x", so the code will not compile (as the compiler cannot find anything to match ::x)
Whether the using namespace directive is employed or not, however, this code will always be unambiguous.
Code:
namespace Junk
{
int x;
}
using namespace Junk; // this line is optional
int main()
{
Junk::x = 42;
}
Now, the next example, we come to the point of namespaces - three things named x, each with different meaning to the program, and all in different namespaces.
Code:
namespace Alpha
{
int x;
}
namespace Beta
{
int x;
}
using namespace Alpha;
using namespace Beta;
int x; // within unnamed namespace
int main()
{
x = 42;
}
This code will simply not compile. The reason is that the compiler has been told, when it is trying to resolve a name, to look in namespaces Alpha and Beta for candidate matches. Because of that, it finds Alpha::x, Beta::x, and ::x as candidates. The compiler has no reason to prefer one candidate over another, so will reject the code (typically with an error message about some form of ambiguity).
If we absolutely must have namespaces Alpha and Beta visible to the compiler then, when compiling this code, there are few options. The first is to remove the "using namespace" directives. So, when it sees "x", the compiler will only consider ::x as a candidate.
If we insist on employing the "using" directives, however, there is no alternative to using the scope resolution operator to resolve the ambiguity.
Code:
namespace Alpha
{
int x;
}
namespace Beta
{
int x;
}
using namespace Alpha;
using namespace Beta;
int x; // within unnamed namespace
int main()
{
::x = 42;
Alpha::x = 50;
Beta::x = 60;
x = 70; // this line will still not compile unless the "using" directives are removed
}
This last sample demonstrates the problem of the "using" directive - once activated, its effects cannot be turned off. So, if ambiguity occurs due to a candidate matches for a name being in multiple namespaces, the ONLY solutions are to remove the offending "using" directives, or to use the scope resolution operator. This is why "using namespace" directives in header files is strongly discouraged - it imposes problems on the code which uses the header file.