Introduction to Namespaces |
|
Notice that there are two classes named house in this program. If you have different people working on the same project, it would not be unusual to have two classes with the same name. The consequence is that, if these classes are used in the same program, the program would not compile. A namespace is a technique of grouping some functions and/or classes to create an entity. This has the main goal of eliminating the probability of having two classes of the same name. For example, if different people work on the same project, each one can create his or her own classes but put them in only his or her namespace. This way, even if they happen to have a class each with the same name, there is no risk of having a name conflict. To create a namespace, type namespace followed by a name. Like a class, a namespace must have a body delimited by an opening curly bracket "{" and ending with a closing curly bracket "}". Here is an example: namespace family { } For the rest of our lessons, we will start the name of a namespace with an uppercase letter. In the body of the namespace, you can create the classes (and/or functions) as you want. Here is an example: namespace Family { struct CHouse { int protect() { return 0; } }; struct CCar { int drive() { return 0; } }; } Remember that the struct or class keyword of a class can be preceded with private or public to control its "visibility" outside of its assembly. Therefore, the above classes can be preceded with the public keyword as follows: namespace Family { public struct CHouse { int protect() { return 0; } }; public struct CCar { int drive() { return 0; } }; } In the same way, you can have as many namespaces as you want. Each namespace can have any valid content. Inside of a namespace, two classes must not have the same name. Inside of a program, two namespaces must not have the same name. Consider this: namespace Family { public struct CHouse { int protect() { return 0; } }; public struct CCar { int drive() { return 0; } }; } int main() { return 0; } As done previously, you can create static methods as members of your classes. This is also valid even if a class is part of a namespace. Here is an example: namespace Family { public struct CHouse { static int protect() { return 0; } }; public struct CCar { int drive() { return 0; } }; } int main() { return 0; } Before accessing a non-static method of a class, you must first create an object from it. Before the type of declaration we saw earlier, you must precede it with the name of the namespace followed by ::. Here is an example: namespace City { public struct CHouse { int showroof() { return 0; } }; } int main() { City::CHouse town; town.showroof(); return 0; } As mentioned earlier, if a method is static, you don't have to create an object from it before using it. You can access it directly by typing the name of the namespace followed by ::, followed by the name of the class. Here is an example: namespace Family { public struct CHouse { static int protect() { return 0; } }; public struct CCar { int drive() { return 0; } }; } int main() { Family::CHouse::protect(); return 0; }
Here is an example: namespace Family { public struct CHouse { static int protect() { return 0; } }; public struct CCar { int drive() { return 0; } }; } int main() { using namespace Family; Family::CHouse::protect(); return 0; } With the using keyword, you can omit the name of the namespace when accessing a class that belongs to the namespace. Here is an example: int main() { using namespace Family; CHouse::protect(); return 0; }
Various namespaces can be part of the same file and the same application. You can create each namespace and specify its own members in its delimiting curly brackets. With various namespaces on the same file or application, you can have the same variables in different namespaces. Here is an example of two namespaces: namespace Family { public struct CHouse { static int protect() { return 0; } }; public struct CCar { int drive() { return 0; } }; } namespace City { public struct CHouse { int showroof() { return 0; } } } To access the member of a namespace, use the :: operator appended to its name and call the desired member. Using the :: operator, you can perform any operation on any member of one namespace applied to a member of another namespace. We saw earlier that the using namespace routine allows accessing the members of a namespace. After typing it, if the name of a variable appears under a using namespace, the compiler would need to reconcile or identify it; if the name of such a variable is not recognized as part of the namespace that is being accessed, the program would not compile. For example, here is an example that uses two using namespaces: namespace Family { public struct CHouse { static int protect() { return 0; } }; public struct CCar { int drive() { return 0; } }; } namespace City { public struct CHouse { static int showroof() { return 0; } }; } int main() { using namespace City; using namespace Family; CHouse::protect(); return 0; } The above program would not compile because the compiler does not understand what house is being referred to in house::protect(): is it the house class of the Family namespace or the house of the City namespace? You would then receive an ambiguous symbol error: .\Exercise.cpp(35) : error C2872: 'house' : ambiguous symbol could be '.\Exercise.cpp(4) : Family::house' or '.\Exercise.cpp(22) : City::house' If you want to use different namespaces with the using namespace routine, each namespace will have to control its scope. One solution would be to create a “physical” scope for each namespace. Here is an example: namespace Family { public struct CHouse { static int protect() { return 0; } }; public struct CCar { int drive() { return 0; } }; } namespace City { public struct CHouse { static int showroof() { return 0; } }; } int main() { { using namespace Family; CHouse::protect(); } using namespace City; CHouse::showroof(); return 0; } Before creating a “physical” scope, we saw that the compiler is able to point out what problem occurred at compilation time. Fortunately, the compiler is able to explicitly designate what problem it encountered. In this case there is a conflict in name resolution: two namespaces have a member of the same name. The solution, which is commonly used, is to qualify the variable that is causing the conflict. You can qualify only the second house call because the compiler will associate the first house call with the first using namespace. The safest way is to qualify both calls of the member, as follows: namespace Family { public struct CHouse { static int protect() { return 0; } }; public struct CCar { int drive() { return 0; } }; } namespace City { public struct CHouse { static int showroof() { return 0; } }; } int main() { using namespace Family; using namespace City; Family::CHouse::protect(); City::CHouse::showroof(); return 0; }
Nesting a namespace is the ability to include a namespace inside (as part of the body) of another namespace. To do this, create the intended namespace as a member of the parent namespace. The nested namespace should have its own name and its own body. Here is an example: namespace Country { namespace City { public struct CHouse { static int showroof() { return 0; } }; } struct CCar { }; } To access a member of a nested namespace, first call its parent, type the :: operator, type the name of the nested namespace, followed by the :: operator, then type the name of the variable you are trying to access. Here is an example: namespace Country { namespace City { public struct CHouse { static int showroof() { return 0; } }; } struct car { }; } int main() { Country::City::CHouse::showroof(); return 0; } Following the same logic, you can have as many namespaces and many nested namespaces in your application as you desire. If you nest a namespace, you can use as many :: operators to qualify each member of the nested namespace you want. You can also use the using namespace routine by qualifying each member inside the using namespace that “needs” its parent: namespace Country { namespace City { public struct CHouse { static int showroof() { return 0; } }; } public struct car { }; } int main() { using namespace Country::City; CHouse::showroof(); return 0; } Otherwise, you can create a using namespace for each namespace and make sure that each one of them controls its scope. As long as you are using the :: operator to identify the member that is being accessed inside of a using namespace, you can call the member of any namespace in any scope, provided you qualify it. |
|
||
Home | Copyright © 2006-2016, FunctionX, Inc. | |
|