GOTW # 30 Name Search (Name Lookup)
Difficulty: 9.5 / 10
Which one is you calling when you call a function? The answer depends on "Name Search", but you will definitely find that it is very surprising.
problem
In the following code, which function is called? why? Analyze the impact.
Namespace a {
Struct X;
Struct y;
Void f (int);
Void g (x);
}
Namespace b {
Void f (INT I) {
f (i); // Which f ()?
}
Void G (a :: x x) {
g (x); // Which g ()?
}
Void h (a :: y y) {
h (y); // Which h ()?
}
}
answer
In the following code, which function is called? why?
Two of them are relatively clear, but the third requirement of the C name search rules - especially Koenig Lookup.
Namespace a {
Struct X;
Struct y;
Void f (int);
Void g (x);
}
Namespace b {
Void f (INT I) {
f (i); // Which f ()?
}
This F () call is itself, and it is endless.
There is also a F (int) function in NameSpace A. If B wrote "Using Namespace A;" or "Using A :: F;", then A :: F (int) will be one of the candidate functions in the F (int) process, that "f (i)" Call will cause an amphony in A:: F (int) and B:: F (int). Since B did not bring A :: F (int) into its spatial range, only B :: F (int) is considered, there is no ambiguity.
Void G (a :: x x) {
g (x); // Which g ()?
}
This call is between A:: G (X) and B:: G (X). The programmer must use the name of the namespace to explicitly limit which G ().
You may start to be strange why you need to do this. After all, like f (), B does not use the "Using" instruction to bring A :: G (x) into its spatial range, so you may think that only B :: g (x) is optional. Didn't say it wrong? Ok, this is a fact, a supplemental rule at the time of the name:
KOENIG LOOKUP (Simplified Edition)
If you provide a Class type of a Class type (here is a :: x type x), the compiler will consider the same name of the namespace containing the real-name type of namespace when the name searches.
This is more complex below, but the substance is the same. This is an example of taking a C standard:
Namespace ns {
Class T {};
Void f (t);
}
Ns :: t parm;
Int main () {
F (PARM); // OK, Calls ns :: f
}
I don't study the necessity of Koenig Lookup here (to extend your thinking, replace "NS" with "std", replace "T" instead with "String", and "f" use "Operator <<" instead Then consider the process again). Looking for more knowledge of Koenig Lookup in the final "Extended Readings", and its impact on name isolation and analysis. You must admit that Koenig Lookup is actually a good thing, you must also understand how it works because it will affect the code you wrote at some time. Void h (a :: y y) {
h (y); // Which h ()?
}
}
There is no other H (A :: Y) function, so f () call itself, and it is endless.
Although the prototype of the B :: H () is a type in NameSpace A, this does not affect the result of the name search because the function that does not match the H (A :: Y) name in Namespace A.
Analysis
To, the meaning of code in Namespace B is affected by the function of complete independent Namespace A, although B is simply referring to a type found in A, there is no thing, even "using" nothing!
This means that there is no dependency between the namespace. Don't rush to condemn namespace; mutual reliance between namespaces is still very perfect, and there is only one T type to establish contacts. In this issue, GOTW just wants to pointed out such a special case, at this time, the namespace is not a passiveness ... and, in fact, in this case, the namespace should not be secret, "extension reading" will This is displayed.
Extension
The impact between namespace and Koenig Lookup is far from the far-reaching far. I want to know why Koenig Lookup is not a vulnerability on the namespace, and how it affects the dependencies between our analysis of the Class, see I published on the March 1998 "What's in a class - the interface Principle".