Login

Username:

Password: 

Join us Now |  Forgot Password? | Forgot UserName?

C++

Learn step by step



Name visibility

Scopes

Named entities like variables, functions, and compound types are need to be declared before being used in C++. Point in the program where declaration happens influences its visibility:

Entity declared outside any block has a global scope, means that its name is valid anywhere. While an entity declared inside a block, such as a function or a selective statement, has a block scope, and is only visible inside the specific block of code in which it is declared.

Variables with a block scope are known as local variables.

E.g., a variable declared in the body of a function is a local variable that extends until the end of the function (i.e., until the brace } that closes the function definition), but not outside the block:

int foo;     // global variable

int some_function ()
{
int bar;     // local variable
bar = 0;
}

int other_function ()
{
foo = 1;     // ok: foo is a global variable
bar = 2;     // wrong: bar is not visible from this function
}

In each scope, a name can represent only one entity. E.g., there cannot be 2 or more than two variables with the same name in same scope:

int some_function ()
{
int x;
x = 0;
double x;     // wrong: the name 'x' is already used in this scope
x = 0.0;
}

Visibility of an entity with block scope extends until end of the block, including inner blocks. But, an inner block, because it is a different block, it can re-utilize a name existing in the outer scope to refer to a different entity; in that case, the name will refer to different entity only inside the inner block. While outside, it will still refer to original entity.
Example:


// inner block scopes
#include <iostream>
using namespace std;

int main () {
int x = 10;
int y = 20;
{
int x;     // ok, inner scope.
x = 50;     // sets value to inner x
y = 50;     // sets value to (outer) y
cout << "inner block:\n";
cout << "x: " << x << '\n';
cout << "y: " << y << '\n';
}
cout << "outer block:\n";
cout << "x: " << x << '\n';
cout << "y: " << y << '\n';
return 0;
}

output

inner block:
x: 50
y: 50
outer block:
x: 10
y: 50

Note: y is not hidden in the inner block, and thereby accessing y still accesses the outer variable.

Variables declared in declarations introduce a block, such as function parameters and variables declared in loops and conditions (such as those declared on a for or an if) are local to block they introduced in.

Namespace

When we use different library modules, there is always a probable for name crashes, as different library may use the same name for different purpose. This problem can be resolved by the use of namespace in C++. Namespace is a collection for identifiers under the same naming scope. (this is known as package in UML and Java.) Entity name under the namespace is qualified by the namespace name, followed by :: (scope resolution operator), such as namespace::entityName.

For placing an entity under a namespace, use the keyword namespace as:

// create a namespace called myNamespace for the enclosed entities
namespace myNameSpace {
int foo;      // variable
int f() { ...... };     // function
class Bar { ...... };     // compound type such as class and struct
}

// To reference the entities, use
myNameSpace::foo
myNameSpace::f()
myNameSpace::Bar

Namespaces are opened. In other words, you can add more names into an existing namespace using additional namespace definition.

Namespaces are particularly useful to avoid the collisions of name. E.g.:


// namespaces
#include <iostream>
using namespace std;

namespace foo
{
int value() { return 5; }
}

namespace bar
{
const double pi = 3.1416;
double value() { return 2*pi; }
}

int main () {
cout << foo::value() << '\n';
cout << bar::value() << '\n';
cout << bar::pi << '\n';
return 0;
}

Output

5
6.2832
3.1416
using

Keyword using introduces a name into current declarative region (such as a block), thus avoiding the need to qualify the name.


// using
#include <iostream>
using namespace std;

namespace first
{
int x = 5;
int y = 10;
}

namespace second
{
double x = 3.1416;
double y = 2.7183;
}

int main () {
using first::x;
using second::y;
cout << x << '\n';
cout << y << '\n';
cout << first::y << '\n';
cout << second::x << '\n';
return 0;
}

Output

5
2.7183
10
3.1416

In this case, by declaring we were using namespace first , all direct uses of x and y without name qualifiers were also looked up in namespace first.

using and using namespace have validity only in the same block in which they are stated or in the entire source code file if they are used directly in the global scope. Example, it would be possible to first use the objects of one namespace and then those of another one by splitting the code in different blocks:


// using namespace example
#include <iostream>
using namespace std;

namespace first
{
int x = 5;
}

namespace second
{
double x = 3.1416;
}

int main () {
{
using namespace first;
cout << x << '\n';
}
{
using namespace second;
cout << x << '\n';
}
return 0;
}

Output

5
3.1416


Related Videos