Scope Resolution Operator (::)
The :: operator establishes ownership of variables and functions.
#include <iostream>
int globalValue = 100;
void demonstrate()
{
int globalValue = 200;
std::cout << "Global variable: " << ::globalValue << std::endl;
std::cout << "Local variable: " << globalValue << std::endl;
}
int main()
{
demonstrate();
return 0;
}
Output:
Global variable: 100
Local variable: 200
Namespace Fnudamentals
Namespace provides a mechanism for organizing code elements into named groups, solving potential naming conflicts in large projects. When projects grow complex with multiple libraries, identifiers may clash. C++ addresses this through the namespace keyword, which partitions identifiers into distinct scopes.
Defining a Namespace
namespace LibraryX
{
int value = 5;
}
namespace LibraryY
{
int value = 15;
}
void checkNamespace()
{
std::cout << "LibraryX value: " << LibraryX::value << std::endl;
std::cout << "LibraryY value: " << LibraryY::value << std::endl;
}
Global Scope Requirement
Namespaces must be defined at global scope. Local definition are prohibited.
void incorrectExample()
{
namespace LocalNS // Compilation error
{
int x = 1;
}
}
Nested Namespaces
namespace Outer
{
int data = 50;
namespace Inner
{
int data = 60;
}
}
void nestedDemo()
{
std::cout << "Outer data: " << Outer::data << std::endl;
std::cout << "Inner data: " << Outer::Inner::data << std::endl;
}
Dynamic Extension
Namespaces remain open and accept new members throughout the program.
namespace Config
{
int timeout = 30;
}
namespace Config
{
int retry = 3;
}
void showConfig()
{
std::cout << "Timeout: " << Config::timeout << std::endl;
std::cout << "Retry: " << Config::retry << std::endl;
}
Variables and Functions in Namespaces
namespace MathUtils
{
int baseNumber = 100;
void calculate()
{
std::cout << baseNumber * 2 << std::endl;
}
}
void testMath()
{
std::cout << "Base: " << MathUtils::baseNumber << std::endl;
MathUtils::calculate();
}
Defining namespace members outside the declaration:
namespace Processor
{
int bufferSize = 1024;
void initialize();
}
void Processor::initialize()
{
std::cout << "Initializing with size: " << bufferSize << std::endl;
}
void externalDefDemo()
{
Processor::initialize();
}
Unnamed Namespaces
Content in an unnamed namespace is accessible only within the current translation unit, functioning similarly to C's static linkage.
namespace
{
int internalData = 999;
void helperFunction()
{
std::cout << internalData * 2 << std::endl;
}
}
void privateAccess()
{
std::cout << internalData << std::endl;
helperFunction();
}
Namespace Aliasing
namespace VeryLongNamespaceName
{
int item = 42;
void display()
{
std::cout << item << std::endl;
}
}
void aliasDemo()
{
namespace Short = VeryLongNamespaceName;
std::cout << Short::item << std::endl;
Short::display();
}
The using Directive
The using namespace directive makes all identifiers within a namespace accessible without qualification.
namespace Alpha
{
int flag = 1;
void report()
{
std::cout << flag << std::endl;
}
}
namespace Beta
{
int flag = 2;
}
void scenarioA()
{
using namespace Alpha; // No ambiguity
std::cout << flag << std::endl;
int flag = 100;
report();
}
void scenarioB()
{
using namespace Alpha;
using namespace Beta;
std::cout << flag << std::endl; // Ambiguity - compiler error
}
The using directive simplifies code but requires careful management to prevent identifier collisions when multiple namespaces with overlapping names are imported simultaneously.