Hello again! In this video, we are going to look at namespaces. Namespaces are another tool for helping
us organize our code.
If you think about that, we already know quite a few ways to do that.
We can divide our code into separate files. Within a file,
we can divide the code into separate functions.
We can organize our data by putting it into structs or classes.
We can also put the code that manages that data into the class.
We can manage object files by creating binary libraries, DLLs or shared objects.
And we can use namespaces for grouping together symbol names, which are logically related.
So typically you do this if you are writing a library. You would create a namespace for your library and
then all your symbols would be defined within that namespace.
One example that we all know and love is the C++ standard library.
This defines the std, standard, STD,
however you pronounce it, namespace.
And this namespace contains the names of all the functions, types and variables that are defined by the
C++ standard library.
Why is this useful? If you are writing a large program like you do in paid-for programming as opposed
to educational programming, you often use several libraries, and it is quite possible that different
libraries decide to use the same name for different symbols.
So you could have two different libraries, which both have a class called Test, to use
our favourite class name. C++ has a "one definition rule" which says that a symbol can only be defined
once, even if you want it to have different meanings.
If we have two different libraries which both have a class called Test, then that is not one definition, that is
two definitions.
So the code will not compile.
One solution, and if you're working in C, it is the only solution.
Obviously, you can't have classes and sea, but you can have structs.
And also, they need to do this to overload functions.
So what you do is to add a prefix to the name which is specific to that library.
So if we work for the Alpha Beta Corporation, we could put abc underscore in front of all our class and
function names, and someone else could put a different prefix for the names. Which is all rather
laborious.
In C++, there is a much better solution, which is to use namespaces.
So we create a namespace for our libraries, so we put namespace and then abc, which is the name of the
namespace.
And then inside the curly brackets, we put all the symbols that we want to declare as being in this
name space.
So every symbol that goes in there is going to be inside this namespace, and the compiler will automatically
put the name of the namespace in front of it.
So we have our class Test in the namespace.
abc. And the compiler will regard this symbol as being abc double colon Test.
This double colon is the scope operator.
You've probably seen it before for member functions, for classes. So that means the member function belongs
to the class.
And this means that the Test symbol belongs to the abc namespace.
And then if we want to refer to this symbol when we're not actually in the same space, we need to
put the namespace name followed by double colon.
So if we want to create a Test object, we put abc double colon Test, and then we can create the object.
So that'll create an object of the test class from the namespace.
abc.
If we have a name which does not belong inside any namespace, it is said to be in the "global" namespace.
This global namespace has no name.
So if we just use a symbol without any qualifier or if we just use an empty scope operator, that will
refer to the global namespace.
If we define a Test class which is not inside a namespace, that will go into the global namespace and
then we can just put "Test"
to get an object or put dobule colon if we want to be specific, that we are referring to the global
namespace.
You are allowed to split namespaces across different parts of the code. So you can start writing a namespace
in one part of the code and break off and then come back later on.
You can even spread it across different files. So you could have a namespace in a header. And then in
a source code file, which includes the header,
you can continue with the namespace, so you could have a class definition which has the members and
the signatures of the member functions.
And then in the C++ source file, you can actually put the function bodies and define the member functions.
What happens if you have a symbol that is defined in two different name spaces?
If there's some sort of hierarchical relationship between them, because namespaces have a hierarchy.
You can actually define namespaces within other namespaces.
So you could put a namespace inside abc. And all namespaces are assumed to be inside the global namespace.
So the global namespace, if you like, it outranks all the namespaces which have names.
If we define x as a symbol in the global namespace and then have another symbol x inside a namespace
abc. If we refer to this x inside the abc namespace, it will refer to its own one.
So this x here will refer to the abc version of x.
We can use the global scope operator, the double colon, and that will give us the global version of
x.
So here is some codes to demonstrate that. We have our variable x in the global namespace.
There is a "using namespace std", which I will talk about in a minute.
We have an abc namespace.
We are defining another variable x, which is inside this namespace.
So this is going to be abc colon colon x, and this is just going to be colon colon x.
We have also defined a function inside this namespace, and this is going to printout the two x's.
So the first x is going to refer to the namespace in abc. And the second x,
This specifies that we wants the one from the global namespace.
And then in the main function, we are calling this function. It is in the abc namespace,
so we put abc colon colon in front of it.
If we miss that out, the compiler will try to find a function in the global namespace called func,
which takes no arguments. And it will not find one.
So we get an error. There we are, identifier
not found.
(So, put that back)
And then when we call this function, it will be in the abc namespace and - well, we have been through
all that.
So let's see if we get the results we expect. And yes, we do.
So x is going to be the x in the abc namespace, value 47, and double colon x is the one from the global namespace with
value twenty three.
And in fact, we could also do...
Just as another example of accessing a variable outside its namespace.
So that's the abc version of x again.
And if we just change that to x, then we will get the global version again.
Twenty three.
Yes.
Good.
There is something called a "using" declaration.
So this will bring a namespace from a lower level namespace into a higher level one.
So for example, we could do this to bring the test class from the xyx namespace into the global namespace.
If we do this outside any namespace definition.
So using xyz colon colon test.
So we are now creating an alias for this name.
So every time we put "Test", the compiler is going to assume that this refers to the xyz version
of Test.
We can still do abc colon colon Test to get the alpha version, and if we want to specifically get the
xyz, we can do xyz colon colon test.
If we need the actual global version, then we have to do colon colon to get the one from the global
namespace.
And then, once we write a using declaration, this will take effect until the end of the enclosing scope.
Or if you do it at the global scope, then it is going to be in effect until the end of the file.
And in fact, you can use the "using" directive to bring in an entire namespace.
So if you put using namespace std.
That will bring every single symbol from the C++ standard library into the global namespace.
So instead of having to put std colon colon and cout we can just put cout. And we can do that.
Now, you have probably noticed that I have been doing that throughout the course.
And you may know that this is not regarded as good practice, and I would actually agree with that,
because this "using namespace" defeats
the point of having namespaces in the first point. Someone has gone to the trouble of creating
a namespace and putting all their symbols in it, and then you go and put them back into the global namespace
again!
So it is all counterproductive. And I would not do this in "real" code for work, but for educational
training examples,
I think it does have value.
The whole point of having an example is to provide the simplest possible example.
And if you have std colon colon for doing something like an iterator to a vector of string, then
you are just going to have an explosion of [colons] and namespace qualifiers. It is quite hard to make
out what the actual code is.
So, that's my excuse anyway!
And I think that is actually quite a common approach amongst instructors.
But because I do it in here, in examples, do not necessarily do it in your workplace. Or if you are a student
and you go out into the big wide world and some says you must not use "using namespace", then they are right
or in my opinion, they are right anyway.
OK.
Sorry, I am rambling a bit! I had better stop there!
So that's it for this video, and I'll see you next time.
But until then, keep coding!