Recapping namespace basics
The namespace
utility was added to C++ to add a scoping level beyond global scope to applications. This feature can be used to allow two or more libraries to be utilized without concern that they may contain duplicative data types, functions, or identifiers. The programmer needs to activate the desired namespace in each relevant portion of their application with the keyword using
. Programmers can also create their own namespaces (usually for creating reusable library code) and activate each namespace as applicable. In the previous examples, we’ve seen the simple use of the std
namespace to include cin
and cout
, which are instances of istream
and ostream
(whose definitions are found in <iostream>
). Let’s review how we can create namespaces ourselves:
#include <iostream> // using namespace std; // Do not open entire std namespace using std::cout; // Instead, activate individual elements using std::endl; // within the namespace as needed namespace DataTypes { int total; class LinkList { // full class definition … }; class Stack { // full class definition … }; }; namespace AbstractDataTypes { class Stack { // full class definition … }; class Queue { // full class description … }; }; // Add entries to the AbstractDataTypes namespace namespace AbstractDataTypes { int total; class Tree { // full class definition … }; }; int main() { using namespace AbstractDataTypes; //activate namespace using DataTypes::LinkList; // activate only LinkList LinkList list1; // LinkList is found in DataTypes Stack stack1; // Stack is found in AbstractDataTypes total = 5; // total from active AbstractDataTypes DataTypes::total = 85;// specify non-active mbr., total cout << "total " << total << "\n"; cout << "DataTypes::total " << DataTypes::total; cout << endl; return 0; }
In the second line of the preceding code (which is commented out), we notice the keyword using
applied to indicate that we’d like to use or activate the entire std
namespace. Preferably, on the following two lines of code, we can instead activate only the elements in the standard namespace that we will be needing, such as std::cout
or std::endl
. We can utilize using
to open existing libraries (or individual elements within those libraries) that may contain useful classes; the keyword using
activates the namespace to which a given library may belong. Next in the code, a user specified namespace is created called DataTypes
, using the namespace
keyword. Within this namespace exists a variable total
, and two class definitions: LinkList
and Stack
. Following this namespace, a second namespace, AbstractDataTypes
, is created and includes two class definitions: Stack
and Queue
. Additionally, the namespace AbstractDataTypes
is augmented by a second occurrence of the namespace definition in which a variable total
and a class definition for Tree
are added.
In the main()
function, first, the AbstractDataTypes
namespace is opened with the using
keyword. This activates all names in this namespace. Next, the keyword using
is combined with the scope resolution operator (::
) to only activate the LinkList
class definition from the DataTypes
namespace. Had there also been a LinkList
class within the AbstractDataType
namespace, the initial visible LinkList
would now be hidden by the activation of DataTypes::LinkList
.
Next, a variable of type LinkList
is declared, whose definition comes from the DataTypes
namespace. A variable of type Stack
is next declared; though both namespaces have a Stack
class definition, there is no ambiguity since only one Stack
has been activated. Next, we use cin
to read into total
, which is active from the AbstractDataTypes
namespace. Lastly, we use the scope resolution operator to explicitly read into DataTypes::total
, a variable that would otherwise be hidden. One caveat to note: should two or more namespaces contain the same identifier, the one last opened will preside, hiding all previous occurrences.
It is considered good practice to activate only the elements of a namespace we wish to utilize. From the aforementioned example, we can see potential ambiguity that can otherwise arise.