Basic requirements of this lecture
* Mastery: The role and definition of namespaces, and how to use namespaces.
* Understanding: Using the early function library
Key points and difficulties
The role and definition of namespaces, and how to use namespaces.
As you learn the previous chapters of this book, the reader has seen several times that the following statements are used in the program:
using namespace Std;
This is the use of the namespace Std. It will be described in more detail in this lecture.
First, why the need for namespaces (issues raised)
namespaces are user-named scopes introduced by ansic++ to handle common conflicts of the same name in programs.
There are 3 levels of scopes defined in the C language, that is, files (compilation units), functions, and compound statements. C + + also introduces a class scope, which appears in the file. Variables of the same name can be defined in different scopes, and the system can distinguish them from each other.
1, the scope of global variables is the entire program, in the same scope should not have two or more entities with the same name (enuty), including variables, functions and classes.
Example: If two classes are defined in a file, there can be functions with the same name in these two classes. When referencing, for the sake of distinction, a class masterpiece should be added to qualify:
class A / /Declare a class
{ public:
void Funl ();//declaring the FUNL function in Class A
private:
int i;
void A::funl () // Define the FUNL function
{...} in Class A.
class B //declaring Class B
{ public:
void Funl (), and FUNL functions in //b class
void fun2 ();
void B::funl () //define the FUNL function in class B
{...}.
This does not confuse.
You can define a global variable in a file, which is scoped to the entire program. If a variable a int a=3 is defined in file A;
In file B, you can define a variable a int a=5;
There is no problem when compiling file A and file B separately. However, if a program includes file A and file B, an error is reported when the connection is made, because there are two variables with the same name in the same program, which is considered a duplicate definition of the variable.
You can declare by extern that a variable of the same name in the two files in the same program is the same variable. If you have the following declaration in file B:
Extem int A;
indicates that variable a in file B is a variable that has been defined in other files. Because of this declaration, the scope of variable A of file A is extended to file B after the program has been compiled and connected. If you no longer assign a value to a in file B, the value of variable A in file A is output in file B: cout<<a; //Gets a value of 3
2, the program will appear name conflict.
in a simple program design, as long as people pay careful attention, you can strive for no errors. However, a large application software, often not by a single person to complete, but by a number of people to work together, different people to complete different parts, the final combination of a complete program. If different people define classes separately, put them in different header files, and when the primary file (the file containing the main function) needs to use these classes, the headers are included with the #include command line. Since the headers are designed by different people, it is possible to name the defined class or function in different header files with the same names.
Example 4 name conflict
programmer A In the header file Headerl. Class student and function fun are defined in H.
The header file Header1 in Example 4 (header file 1, no file name is Cc8-4-h1.h)
#include <string>
#include <cmath>
using namespace Std;
Class Student //Declaration Student Classes
{ public:
Student (int n,string nam,int a)
{ num=n;name=nam;age=a;}
void Get_data ();
Private
int num;
String name;
int age; };
void Student::get_data () //member function definition
{cout<<num<< "" <<name<< "" <<age<<endl;}
Double Fun (double a,double b)//define global functions (that is, external functions)
{return sqrt (a+b);}
Include the header file Headerl.h in the file where the main function resides:
#include <iostream>
using namespace Std;
#include "header1.h" //Note to use double quotes, because files are generally placed in the user directory
int main ()
{Student stud1 ("Wang", 18); //Define Class object Studl
Stud1.get_data ();
Cout<<fun (5,3) <<endl;
return 0; }
Program can run normally, output as
18 Wang
2.82843
If programmer B writes the header file Header2. H, in addition to defining other classes, also defines the class student and function fun, but its contents are headerl with the header file. The student and function fun in H are different.
The header file in
//Case 4 Header2
#include <string>
#include <cmath>
using namespace Std;
class Student //Declaration Student class
{public:
Student (int n, String Nam,char s) //parameter differs from student in Headerl
{num=n;name=nam;sex=s;}
void Get_data ();
Private:
int num;
string name;
char sex;} ;//This item differs from Headerl
void Student::get_data () //member function definition
{cout<<num << "" <<name<< "" <<sex<<endl;}
Double Fun (double a,double b) //define global functions
{return sqrt (a-b);} //Return value is different from fun function in Headerl
//header file 2 There may be other content
If the master programmer uses Headerl in its program. The student and function fun in H, thus including the header file Headerl in the program. H, at the same time to use the header file Header2. Some of the content in H (but for Header2. h contains no knowledge of classes and functions with the same name as the student class and the fun function in headerl.h, because there are often many different pieces of information in a header file, and users tend to care only about the parts they need without paying attention to other content. Thus, the header file Header2 is included in the program. H. If the primary file (the file that contains the main function) is as follows:
#include <iostream>
using namespace Std;
#include "header1.h"//Include header file L
#include "header2.h"//Include header file 2
int main ()
{Student stud1 ("Wang", 18);
Stud1.get_data ();
Cout<<fun (5,3) <<endl;
return 0; }
then the program compiles and there is an error. Because after the precompilation, the contents of the header file replace the corresponding #include command line, so that there are two student classes and two fun functions in the same program file, which is clearly a duplicate definition, which is the name conflict, in which there are two or more entities with the same name in the same scope.
3, global namespace pollution (namespace pollution).
in the program also often need to refer to some libraries (including C + + compiler system provided by the library, the software developers provided by the library or the user's own development of the library), for this need to include the relevant header files. If the libraries contain entities with the same name as the global entity of the program, or if there are identical entity names in different libraries, a name conflict occurs at compile time.
to avoid this kind of problem, many methods have been proposed, such as: to write the name of the entity long-some (including more than 10 or dozens of letters and characters); To make the name special, including some special characters; the internal global identifiers provided by the compilation system are prefixed with an underscore, such as _ Complex () to avoid the same name as the entity named by the user; the name of the entity provided by the software developer is prefixed with a specific character. But this effect is not ideal, but also increased the difficulty of reading procedures, readability reduced.
the C language and the early C + + language did not provide an effective mechanism for solving this problem, and did not allow the library's providers to build their own namespaces. It is hoped that the ANSI C + + standard solves this problem by providing a mechanism and a tool that distinguishes the global identifier named by the designer of the Library from the global entity name of the program and the global identifier of other libraries.
Ii. What is a namespace (solution)
namespaces : In fact, an area of memory that is named by a program designer, the programmer can specify some namespace domains with names as needed, and place some global entities in each namespace, separating them from other global entities.
such as: namespace ns1 //designated Middle NSL
{int A;
double b; }
namespace is a keyword that must be written to define namespaces, NSL is the name of the namespace that the user specifies (you can use any legal identifier, and here ns1 is because NS is the abbreviation for namespace, meaning please chu), within the curly braces is a declaration block in which the entity declared is called a namespace member (namespace). namespace members now include variables A and B, noting that A and B are still global variables, simply hiding them in the specified namespace. If you want to use variables A and B in your program, you must add the namespace name and scope resolution "::", such as nsl::a,nsl::b. This usage is called a namespace qualifier (Qualified), and these names (such as nsl::a) are called qualified names (qualified name). The role of namespaces in C + + is similar to the directory and file relationships in the operating system, because many files, inconvenient to manage, and easily duplicate the name, so people set up a number of subdirectories, the files are placed in different subdirectories, the different subdirectories of the file can have the same name. The file path should be indicated when the file is called.
the role of namespaces is to create some separate scopes, separating some global entities. lest there should be an old point called Lee Sang, 3 people stand up to answer, this is the name conflict, because they can not tell what the teacher want to call the Lee Sang, the same name can not distinguish between. To avoid confusion of the same name, the school divided 3 students with the same name in 3 classes. In this way, when a small class name Lee Sang, only one person will answer. In other words, the name is unique within the class scope (i.e. class scope). If the headmaster call in the whole school, need to look for this student in the entire school area, need to consider the scope problem. If the headmaster called Lee Sang, there will be 3 students in the whole school shouting "to", because there are 3 students with the same name in the same scope. In order to differentiate the 3 students in the whole school, the headmaster must add the class number before the name, such as the Lee Sang of the senior class, or the Lee Sang of Class B, that is, the class name is limited. This will not lead to confusion.
You can set many namespaces as needed, each of which represents a different namespace field, and different namespaces cannot have the same name. In this way, the entities in different libraries can be placed in different namespaces, or, in different namespaces, different entities are concealed. The global variables we used in the past can be understood as global namespaces, independent of all well-known namespaces, that are not required to be declared with namespace, are actually implicitly declared by the system, and exist in each program.
When declaring a namespace, you can include not only variables in curly braces, but also the following types:
• Variables (can be initialized);
constant
• Number (can be defined or declared);
• Structural body;
Class
Template
• Namespaces (a namespace is defined in a namespace, which is a nested namespace).
For example
namespace NSL
{ const int rate=0.08; //Constants
doublepay //variable
doubletax () //function
{return a*rate;}
namespacens2 //nested namespaces
{int age;}
}
If you want to output data for a member in a namespace NSL, you can use the following method:
cout<<nsl::rate<<endl;
COUT<<NSL::p ay<<endl;
Cout<<nsl::tax () <<endl;
cout<<nsl::ns2::age<<endl; //need to specify the middle name of the outer and inner layers
you can see that namespaces are declared and used in the same way as classes. But there is a difference: when declaring a class, there is a semicolon behind the right curly brace, and there is no semicolon behind the curly brace when defining the namespace.
Third, using namespaces to resolve name conflicts (use guide)
With the above foundation, namespaces can be used to solve the name conflict problem. Now, modify the example 4 program to make it work correctly.
Example 5 uses namespaces to resolve example 4 program name conflict issues.
Modify two header files to place the classes declared in the header file in two separate namespaces.
In example 8.5, header file 1, file name is Header1.h
using namespace Std;
#include <string>
#include <cmath>
namespace ns1 //Declaration namespace ns1
{class Student //Declare Student class within namespace NSL
{public:
Student (int n,string nam,int a)
{Num=n;name=nam; Age=a;}
void Get_data ();
Private:
int num;
string name;
int age; ;
void Student::get_data () //Defining member functions
{cout<<num<< "" < <name<< "" <<age<<endl;}
Double Fun (double a,double b) //define the fun function within the namespace N citation
{return sqrt (a+b);}
}
//Case 8.5, header file 2, file name is Header2.h
#include <string>
#include <cmath>
Namespace NS2 //Declaration namespace NS2
{class Student
{public:
Student (int n,string Nam,char s)
{num=n;name=n Am;sex=s;}
void Get_data ();
Private:
int num;
string name;
char sex;} ;
void Student::get_data ()
{cout<<num<< "<<name<<" <<sex< <endl;
Double Fun (double a,double b)
{return sqrt (a-b);}
}
Main file
#include <iostream>
#include "header1.h" //Include header file L
#include "header2.h" //Include header file 2
int main ()
{ns1::student stud1 ("Wang", 18); ///using the Student class declared in the namespace NSL Studt
Stud1.get_data (); //Do not write Ns1::studl.get_data ();
Cout<<ns1::fun (5,3) <<endl; //Call the fun function in the namespace ns1
Ns2::student stud2 (102, "Li", ' f '); ///using the Student class declared in the namespace ns2 stud2
Stud2.get_data ();
Cout<<ns2::fun (5,3) <<endl; //Call namespace NSL, fun function in
return 0; }
The key to solving this problem is to set up two namespaces NSL and NS2, and put classes that originally sound in two header files into namespaces NSL and NS2 respectively. Note: In the header file, do not place the #include command in the namespace, as you can see in the description in the previous section that the contents of the namespace do not include the command line, otherwise the compilation will fail.
The reason for parsing Example 4 program error is that there is the same class name student and the same function name fun in the two header files, and there is a name conflict when they are included in the main file, and there is a duplicate definition. The compilation system cannot tell which header file student to define the object studl. Now two student and fun are placed in separate namespaces, each of which has its own scope and is irrelevant. Because the scope is not the same, will not produce: a name conflict. Just as you can have variables and functions with the same name in two different classes, you don't have a conflict.
The studl is defined with Ns1::student (Student in the namespace NSL) when the object is defined, and ns2::student is defined with NS2 (Student in the namespace Stud2). Obviously, Nsl::student and Ns2::student are two different classes that don't create confusion. Similarly, namespace name NS] or NS2 are required to qualify when calling the fun function. Ns1::fun () and Ns2::fun () are two different functions. Note: Object studl is defined with Nsl::student, but the object studl is not in the namespace NSL. The scope of the studl is scoped to the main function. You should write studl when you call the member function Get_data of the object studl. Get_data () should not be written as Nsl::studl.get_data ().
The program can be successfully compiled and the following results are obtained:
Wang L9 (data in Object studl)
2.82843 (value of/5+3)
102 Li F (data in Object STUDG)
1.41421 (/5-2 of the value)
Iv. methods of using namespace members
As you can see from the above introduction, when referencing namespace members, namespace members are qualified with namespace names and scope specifiers to distinguish between identifiers of the same name in different namespaces. That
Namespace name:: namespace member name
This method is effective in ensuring that the referenced entity has a unique name. However, if the namespace name is longer, especially in the case of namespace nesting, a long name is required to refer to an entity. It may be inconvenient to refer to a namespace member more than once in a program.
1. Using namespace aliases
You can use an alias (namespace alias) for a namespace to replace a longer namespace name. as
Namespace Television//declares the namespace, named television
{ ... }
You can replace it with a short, easy to remember alias. Such as:
namespace Tv=television; //Alias TV and original television equivalence
It can also be said that the alias TV pointed to the original television, in the former television position can be unconditionally replaced by TV.
2. Use namespace member name
The namespace member name after using must be a namespace-qualified name. For example:
Using Nsl::student;
The above statement declares that the member student in the namespace ns1 is used in this scope (the scope in which the using statement is located), and if you use the namespace member in this scope, you do not have to use namespace qualification. For example, after using the using declaration above, the Student appearing in the subsequent program is implicitly referring to Nsl::student.
The valid scope of a using declaration is from the start of the using statement to the end of the scope where the using is located. If you have the following statement after the using statement above:
Student studl ("Wang", 18);//Here the Student equals ns1::student
The above statement is equivalent to
nsl::student studl ("Wang",);
And AS
The fun that appears after the using Nsl::fun//declaration is within the namespace NSL fun
Cout<<fun (5,3) <<endl;//The fun function here is equivalent to Nsl::fun (5,3)
Obviously, this avoids using namespace qualification every time that you reference a namespace member, making referencing namespace members easy to use.
Note, however, that you cannot have members of the same name in a member of a different namespace with a using declaration in the same scope. For example:
Usmgnsl::student///declaration The Student that appears later is the Student in the namespace NSL
Usmgns2::student//Declaration The Student that appears later is the namespace ns2 small Student
Student stud1; /What is the name of the student in the middle of the student?
Generated two semantics, compilation error.
3. Use namespace namespace name
With the using namespace member name described above, only one namespace member can be declared at a time, and if 10 entities are defined in one namespace, you need to use a 10-time using namespace member name. Can you declare all members of a namespace once in a program with one statement?
C + + provides a using namespace statement for this purpose. The general format of a using namespace statement is
using namespace namespace name;
For example
Using Nanlespace NSL;
Declares that a member in a namespace NSL is to be used in this scope and that no namespace qualification is required when any member of the namespace is used. If you make the statement above, you have the following statement:
Student studl ("Wang",); //student implicitly refers to the Student in the middle NSL
Cout<<fun (5,3) <<endl; //The fun function here is the fun function in the named Middle NSL
In scopes declared with Usmgnamespace, the members of the namespace NSL are as if they were declared in the global domain. Therefore, you do not have to qualify with namespaces. Obviously this kind of processing is more convenient for writing programs. However, if you use UsingNamespace to declare multiple namespaces at the same time, you are often prone to error. The main function in Example 5, if replaced with the following program segment, will make an error.
int main ()
{using namespace NSL;//declaring that members in NSL are available in this scope
using namespace ns2;//declaring that members in NS2 are available in this scope
Student studl ("Wang", 18);
Studl.8ct_data ();
Cout<<fun (5,3) <<endl;
Student stud2 (102, "Li", ' R ');
Stud2.get_data ();
Coutt<<fun (5,3) <<endl;
return O;}
Because two namespaces NSL and NS2 are introduced in the same scope, there are classes and functions with the same name. In the presence of student, can not determine which namespace of the student, there are two semantic, compilation error. Therefore, use namespace statements are used only if the number of namespaces is very small and if there are no members of the same name in those namespaces.
V. Nameless namespaces
As described above is a namespace with a name, C + + also allows namespaces with no name, such as the following unnamed namespaces declared in file a:
namespace//namespace has no Name
{void fun ()//Defining namespace members
{cout<< "OK. "<<endl;}
}
Because namespaces are not named and are clearly not referenced in other files, they are only valid within the scope of this file. Members of nameless namespaces the scope of the fun function is file a (specifically, from the point where the unnamed namespace is declared to the end of file a). Using a member of a nameless namespace in file A does not have to (and cannot) be qualified with a namespace name.
If you have the following statement in file a:
F