tags:
- Cpp
Using Keyword in C++ (ENG)
Do this at first: Namespaces in C++ (ENG)
We will add some details about what happens behind the scenes in this section. Before that, make sure you have completed the namespace part.
We use the using
declaration to introduce namespace members into other namespaces and block scopes. Global functions and variables can also be introduced into other namespaces using using
declarations. This might sound dizzying, but no hard to understand.
Without further ado, let's dive into some code:
#include <iostream>
void func(); // Global function declaration
int var; // Global variable
void func(){ // Global function difinition
std::cout << "In global func." << std::endl;
}
namespace A {
void A_func(); // A::A_func(), this is also global, but with a suffix name A
}
void A::A_func(){
std::cout << "In A::A_func." << std::endl;
}
namespace B {
using ::func; // Global func() is now visible as B::func
using ::var; // Global var is now visible as B::var
using A::A_func; // A::A_func() is now visible as B::A_func
}
int main() {
var = 0;
std::cout << var << std::endl;
::var = 10; // Modify the global variable to 10
std::cout << ::var << std::endl;
B::var = 20; // Okay
std::cout << ::B::var << std::endl;
B::func(); // Calls func() // as the same as ::func() or func()
B::A_func(); // Calls A::A_func()
return 0;
}
This code demonstrates how you can introduce global variables and functions into a namespace using the using
declaration. By doing this, you make global names accessible within the namespace B
, allowing you to use them without fully qualifying their names.
And once you can do the step forward, you can do the backward. This is allowed as well:
namespace A {
int var; // A::var
}
using A::var; // A::var is now available as ::var
int main() {
::var = 10; // This refers to A::var
A::var = 30; // refers to A::var
return 0;
}
But when you introduce names from one namespace into another, you need to be cautious not to create ambiguities. If two namespaces have members with the same name, using declarations can lead to confusion and potential conflicts.
When you use a using
declaration within a block scope, it's often referred to as a using
directive within that block. Which we have seen as in using namespace blabla;
.
This is a example from cppreference:
namespace A
{
int i;
}
namespace B
{
int i;
int j;
namespace C
{
namespace D
{
using namespace A;
// Names from A are "injected" into D.
// Unqualified lookup within D considers these names to have the same
// scope as the global scope (e.g. for the purposes of name hiding).
// Qualified lookup referring to D (D::name for some name)
// will find the same name as unqualified lookup within D.
int j;
int k;
int a = i; // i is B::i, because A::i is hidden by B::i
int b = ::i; // error: there is still no i in the global namespace
}
using namespace D; // names from D and A are injected into C
int k = 89; // OK to declare name identical to one introduced by a using
int l = k; // ambiguous: C::k or D::k
int m = i; // ok: B::i hides A::i
int n = j; // ok: D::j hides B::j
}
}
// These are all equivalent definitions:
int t0 = B::i;
int t1 = B::C::a;
int t2 = B::C::D::a;
using
You can create type aliases with the using
keyword, similar to typedef
.
using cout = std::cout;
int my_variable = 0;
using var = my_variable;
typedef my_variable = var; // same
You can also create type aliases for template classes using using
. This is true beast, which typedef
cannot do.
template<class T> using myClass = myOriginalClass<T>;
// typedef syntax is not allowed with templates:
template<class T> typedef myOriginalClass<T> myClass; // error, this is not allowed