Class scope and namespace continuation-leave questions in the future

Source: Internet
Author: User

Class scope and namespace continuation

(Name Search rules)

 

In version 4, there is a paragraph about the Name Lookup in the class scope:

So far, in our program,Name Search (the process of searching for declarations that match the given name)Is relatively direct.

(1) First, find the name declaration in the block using the name, You only need to consider the name declared before this item is used.

(2) If the name cannot be foundSurrounding scope (the outer scope also needs to be used before).

(3) C ++All names must be declared before use.

(4) During name search, if the name used by the class scope cannot be determined as the member name, search for the name declaration in the scope containing the class or member definition.

Knowing that the theory does not understand the essence, or that the understanding may be biased. Next we will continue to do a small test. The test procedure is as follows:

// FindName header file

Class client {public: client () {}client (client & c ){}~ Client () {} void CallShow () {void show (); // Show (); function templates cannot be separately declared, the private: int id;}; templateclass server {public: server () {} server (server & s ){}~ Server () {} void CallShow () {void show (); // Show ();}};
// FindName. cpp # include <iostream> # include "findName" using namespace std; void show () {cout <"Wellcome to call me! "<Endl;} template <class T> void Show () {cout <" 0 = "<static_cast (0) <endl;} int main () {client cus; cus. callShow (); server hos; hos. callShow (); Show (); // note that no parameter template function calls Show ();}

 

# Include "findName"

It is easy to understand thatThe findName file is directly copied to the current location, so in a file, we can easily understand why show and Show cannot be called,We cannot use a name before it is declared.

There are two solutions if we have to call the program.:

Solution 1:

#include<iostream>void show(){   std::cout<<"Wellcome to callme!"<<std::endl;}template<class T>void Show(){   std::cout<<"0 =="<<static_cast(0)<<std::endl;}#include"findName"using namespace std; int main(){   client cus;   cus.CallShow();   server hos;   hos.CallShow();   Show();   Show();   Show();}

 

Solution 2:

# Include <iostream> void show (); template <class T> // The template has no forward declaration method. void Show () {std :: cout <"0 =" <static_cast (0) <std: endl;} # include "findName" using namespace std; void show () {std :: cout <"Wellcome to callme! "<Std: endl;} int main () {client cus; cus. callShow (); server hos; hos. callShow (); Show ();}

The scope style above is actually the global scope of C ++. We can use the namespace of C ++.

 

Naming rules for namespaces:

(1) class member functions take precedence (by subclass ---> base class order). Once found, the function is stopped.

(2) If no, search in the corresponding namespace (for example, usingnamespace std; search in std ).

(3) If no, search for the parameter based on its namespace.

 

Function call matching principle: (I understand)

(1) first match the function name. If the function name can be found, perform the next matching.

(2) then match the function type. If the function type cannot be matched (for example, the parameter is generic), it will be matched again during instantiation.

(3) Strict matching is required during instantiation.

That is to say, a template can be called before a function appears. However, when calling a template, parameters must have generic parameters, the called function must appear in the relevant namespace before.

 

Let's take a look at a simple example:

#include<iostream>

#include<string>

template<class T>void CallShow(){ //Show(); //Show(std::string("empty"));} template<class T>void CallShow(T s){ //show(); Show(s); //Show(std::string("empty"));} template<class T>class display{public: void CallShow(T s) { Show(s); }}; void Show(){ std::cout<<"Empty Show!"<<std::endl;}void Show(std::string s){ std::cout<<"s = "<<s<<std::endl;}int main(){ CallShow(); std::string str = std::string("song"); CallShow(str); display d; d.CallShow(str);}

From this test, we can conclude that:

(1) The reason why Show (s) is called successfully is that it is defined only when the template function is instantiated.

And the instantiation must occur during the call.

(2) An error occurred while calling Show () because the function does not have any generic parameters. Therefore, the compiler can make a choice directly, so it will match the function before the template function is instantiated. At this time, Show () is not defined, so the call fails.

(3) Show (std: string ("empty") call failure is the same as (2 ).

(4) Pay attention to the call method of CallShow.

 

Put the following code in namespace std:

void Show(){   std::cout<<"Empty Show!"<<std::endl;} void Show(std::string s){   std::cout<<"s = "<<s<<std::endl;}
namespace std{void Show(){   std::cout<<"Empty Show!"<<std::endl;} void Show(std::string s){   std::cout<<"s = "<<s<<std::endl;}}

The call is still successful. This does not conform to our understanding, because we did not specify the name domain std: Show when calling Show, which seems unreasonable. In fact, this is the third rule for name search:Search by parameter namespace.

Write two statements in the mian function:

Show ();

Show (std: string ("test "));

As expected, the first compilation error occurs: The function name cannot be found. The second statement is successfully executed.

When std is changed to stdl, both sentences cannot be compiled.

 

When Show is not placed in namespace std, while CallShow and display is placed in namespace std.

namespace std{template<class T>void CallShow(){   //Show();   //Show(std::string("empty"));} template<class T>void CallShow(T s){   //show();   Show(s);   //Show(std::string("empty"));} template<class T>class display{ public:   void CallShow(T s)   {        Show(s);   }};}

The compilation fails. The error is obvious when CallShow is used. The scope restriction std: Must be added during display ::.

If namespace std is added, the execution will also pass completely.

 

If the code is changed to the following:

#include<iostream>

#include<string>

namespace std{void Show(int i){}template<class T>void CallShow(){ //Show(); //Show(std::string("empty"));} template<class T>void CallShow(T s){ //show(); Show(s); //Show(std::string("empty"));} template<class T>class display{ public: void CallShow(T s) { Show(s); }};} namespace std{void Show(){ std::cout<<"Empty Show!"<<std::endl;} void Show(std::string s){ std::cout<<"s = "<<s<<std::endl;}} int main(){ std::CallShow(); std::string str = std::string("song"); std::CallShow(str); std::display d; d.CallShow(str); //Show(); Show(std::string("test"));}

The program can implement normal functions.

However, if the namespace std of Show is removed, a compilation error will occur. At this time, CallShow only matches the Show in std, which is a C ++ matching rule.If it is found in the namespace, it will not be searched in the outer scope. There is no overload mechanism between different namespaces.

In this example, the Show in Std does not form a heavy load with the global Show, and when the Show is found in std, it will not look for the outer layer (this is actually the name blocking principle in C language, globally blocked. You can use ":" To display the call ). Then an error occurs because the parameters do not match.

However, ":" cannot be used here. The reason is unknown.

If you remove the Show definition in std, you can find that the Show in the global space runs normally.

 

A small conclusion: The namespace can directly use the name in the global space, and vice versa (like std: :) must be used ::).

 

Let's change the code again:

#include<iostream>

#include<string>

namespace std{void Show(int i){}template<class T>void CallShow(){ //Show(); //Show(std::string("empty"));}template<class T>void CallShow(T s){ //show(); Show(s); //Show(std::string("empty"));}template<class T>class display{public: void CallShow(T s) { Show(s); }};}int main(){ std::CallShow(); std::string str = std::string("song"); std::CallShow(str); std::display d; d.CallShow(str);}namespace std{void Show(){ std::cout<<"Empty Show!"<<std::endl;}void Show(std::string s){ std::cout<<"s = "<<s<<std::endl;}}

It is hard to understand how this code can be successfully executed. Isn't Show defined after instantiation? Leave this question to the end of the template later.

 

 

 

 

 

 

 

 

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.