I. Relevant knowledge points
The names that are usually placed in the header file, like constants, inline functions (inline function), are internally connected by default (although constants are internally connected by default in C + +, in c it defaults to external connections). Note that connections only refer to those members that have addresses during connection/mount, so class declarations and local variables are not connected.
The creation of namespaces is very similar to the generation of a class:
Namespace mylib{
Declarations
}
This creates a new namespace that contains the various declarations. namespace differs from class, struct, union, and enum:
1) namespace can only be defined in the global category, but they may be nested with each other.
2) at the end of the namespace definition, there is no need to follow a semicolon after the right curly brace.
3) A namespace can be defined in multiple header files with an identifier, as if a class is defined repeatedly.
4) A namespace name can be aliased with another name, so we don't have to beat the lengthy names that developers provide.
5) We cannot create an instance of a namespace like a class.
1. Unnamed namespaces
Each compilation unit can contain an unnamed namespace-there is no identifier after the namespace keyword.
Within the compilation unit, the names in this space are automatically and indefinitely valid. Each compilation unit ensures that there is only one unnamed namespace. If you put a local name in an unnamed namespace, you can make the internal connection without adding a static description.
2. Friends
A friend declaration can be inserted within the class definition of a namespace:
Namespace me{
Class us{
//...
Friend You ();
};
}
Using namespaces
There are two ways to reference the same name in a namespace: one with the range decomposition operator and one with the Using keyword.
1. Scope decomposition
Any naming in the namespace can be explicitly specified with the range decomposition operator, just as it would refer to a name in a class.
2. Using directives
Using the Using keyword allows us to immediately enter the entire namespace and get rid of the annoyance of entering identifiers in a namespace. This use and namespace keyword collocation is called a using directive. The Using keyword directly declares all the names in the namespace in the current scope, so it's easy to use these unrestricted names.
It is now possible to declare all the names in M a t h inside the function, but allow the names to be nested inside the function.
A disadvantage of the using directive is that it does not seem so intuitive that the using directive introduces the scope of the name visibility to where the using is created. But we can make the names from the using directives temporarily invalid, just as they have been declared as global names for this range.
If there is a second namespace
This namespace is also introduced with using directives, which can create conflicts. This ambiguity occurs when the name is used, rather than when the using directive is used.
Thus, even if there is never a two semantic, it is possible to write using directives to introduce namespaces with name collisions.
3. Using declarations
You can use a using declaration to introduce names to the current scope at once. Instead of looking at the name as the global name of the current scope as the using directive does, this method makes a declaration within the current scope, which means that it can discard the name from the using directive within this scope.
The using declaration gives the full name of the identifier, but no information about the type. That is, if a namespace contains a set of functions that are overloaded with the same name, the using declaration declares all functions within the overloaded collection. The using declaration can be placed where any general declaration can occur. A using declaration is only a little different from a normal declaration: a using declaration can cause a function to be overloaded with the same parameter type (which is not allowed in a generic overload). This uncertainty, of course, is only shown when it is used, not when it is declared. A using declaration can also appear within a namespace, as it does elsewhere:
A using declaration is an alias that allows us to declare the same function in different namespaces. If we do not want a function to be repeatedly defined due to a function that introduces a different namespace, you can use a using declaration, which does not cause any uncertainty or duplication.
Convert connection specified
What if you write a program in C + + that requires a C library? If you declare a C function like this:
float f (int a,char B);
The C + + compiler will turn this name into something like _f_int_int to support function overloading (and type-safe connections). However, a library compiled by the C compiler generally does not do such conversions, so its internal name is _f. In this way, the connector will not be able to resolve our C + + call to f ().
A connection transformation designation is provided in C + +, which is implemented by overloading the extern keyword. extern is followed by a string to specify the connection type of the function we want to declare, followed by the function declaration.
extern "C" float f (int a,char B);
This tells the compiler that F () is a C connection, so that the function name is not converted. Standard connection type specifiers have both "C" and "C + +", but compiler developers can choose to support other languages in the same way.
If we have a set of declarations that convert connections, you can put them in curly braces:
or in the header file:
Most C + + compiler developers handle conversion connection designations in their header files, including C and C + +, so we don't have to worry about them.
Although standard C + + supports only "C" and "C + +" Connection conversion designations, support for other languages can be implemented in the same way.
Two. Related code
1.
<span style= "FONT-SIZE:18PX;" ><strong>/* This is another example of the preprocessor that is still useful, as the _ File_ and _line_ instructions work only with the preprocessor and in the Assert () macro. If the assert () macro is called in an error function, it prints only the line number and file name of the wrong function instead of calling the wrong function. Here is a way to use a macro join (many of the Assert () methods) functions, followed by Call assert () (this is eliminated by a # define NDEBUG after the program has been successfully debugged). *//*allege.h*/#ifndef allege_h_#define allege_h_#include <stdio.h> #include <stdlib.h> #include < assert.h>inline void Allege_error (int val, const char* msg)//function Allege_error () has two parameters: one is the value of the integer expression and the other is the value// False to print the message {if (!val) {fprintf (stderr, "Error:%s\n", msg);//function fprintf () instead of IOStreams because it works//better in the case of only a small number of errors. If this is not established for debugging, exit (1) is called to terminate the program. #ifdef ndebugexit (1); #endif}}//allege () macro uses the Triad If-then-else to force the evaluation of expression expr. //allege_error () is called in the macro, followed by assert (), so we can gain the benefit of assert () while debugging//--because some environments tightly combine the debugger with the Assert (). #define Allege (expr, msg) {allege_error (expr) 1:0, msg); assert (expr);} #define ALLEGEMEM (expr) allege (expr, "out of Memory")//allegefile () macro is the allege () macro used to check the file's private version # define ALLEGEFILE (expr) all Ege (expr, "could not open file")//allegemen () macro is a allege () macro used toCheck the dedicated version of memory #endif </strong></span>
<span style= "FONT-SIZE:18PX;" ><strong> #include <iostream> #include "ALLEGE.h" using namespace Std;char Onechar (const char* string = 0) { static const char* S;IF (string) {s = String;return *s;} Else{allege (S, "un-initialized S");} if (*s = = ' + ') {return 0;} return *s++;} char* a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int main () {Onechar (a); Char c;while ((c = Onechar ()) = = ' + ') {cout << c << ; Endl;} return 0;} </strong></span>
2.
<span style= "FONT-SIZE:18PX;" ><strong>/*funobj.cpp*/#include <iostream>using namespace std;//defines a static X-type object inside the function f (). It can be initialized with a constructor with parameters, or it can be used with the//default constructor. The constructor is only required when the program controls the first time to go to the object's definition point and only the first time. Class X{int i;public:x (int i = 0): I (i) {}~x () {cout << "x::~x ()" << Endl;}}; void F () {static x x1 (n); static x x2;} int main () {f (); return 0;} </strong></span>
3.
<span style= "FONT-SIZE:18PX;" ><strong>/* the destructor of a static object *//*statdest.cpp*/#include <fstream.h>ofstream out ("Statdest.out"); class obj{ Char c;public:obj (char c): C (c) {out << ' obj::obj () for "<< C << Endl;} ~obj () {out << ' obj::~obj () for "<< C << endl;}};o BJ A (' a '); void f () {static obj B (' B ');} void G () {static obj C (' C ');} int main () {out << ' inside main () ' <<endl;f (); G (); out << "leaving Main ()" << Endl;} </strong></span>
4.
<span style= "FONT-SIZE:18PX;" ><strong>/* an initialization expression for a static member is within the scope of a class *//*statinit.cpp*/#include <iostream>using namespace std;// Withstatic:: Qualifier extends the range of withstatic to all definitions int x = 100;class withstatic{static int x;static int y;public:void print () const{ cout << "withstatic::x =" << x << endl;cout << "withstatic::y =" << y << Endl;}}; int withstatic::x = 1;int withstatic::y = x + 1;int main () {withstatic WS; Ws.print (); return 0;} </strong></span>
5.
<span style= "FONT-SIZE:18PX;" ><strong>/* static array *//*statarry.cpp*//* for all static data members, we must provide a single external definition. These definitions must have an internal connection, so they can be placed in the header file. The method of initializing a static array is the same as the initialization of other collection types, but cannot be automatically counted. In addition, at the end of the class definition, the compiler must know enough class information to create the object, including the exact size of all members. */#include <iostream>using namespace std;class values{static const int size;static const FLOAT Table[4];static cons T letters[10];}; const int values::size = 100;const float Values::table[4] = {1.1, 2.2, 3.3, 4.4};const values::letters[10] = {' A ', ' B ', ' C ', ' d ', ' e ', ' f ', ' g ', ' h ', ' I ', ' J '};int main () {return 0;} </strong></span>
6.
<span style= "FONT-SIZE:18PX;" ><strong>/* nested classes and local classes make it easy to place a static data member in a nested one. However, there cannot be a static data member in a local class (a class defined within a function) *//*local.cpp*/#include <iostream>using namespace Std;class outer{class inner{ static int I;//ok};}; int outer::inner::i = 47;void F () {class foo{public://!static int i;} x;} int main () {return 0;} </strong></span>
7.
<span style= "FONT-SIZE:18PX;" ><strong>/* static data members and static member functions are used together with *//*sfunc.cpp*/#include <iostream>using namespace std;//because static member functions do not have This pointer, so it cannot access non-static data members, and cannot tune//with non-static member functions that use the this pointer). Class X{int i;static int j;public:x (int i = 0): I (i) {j = i;} int Val () Const{return i;} static int incr () {//!i++:static member Functionreturn +j;} static int F () {//!val (); return incr ();}}; int x::j = 0;int Main () {x x; x* XP = &x;x.f (); Xp->f (); X::f (); return 0;} </strong></span>
8.
<span style= "FONT-SIZE:18PX;" ><strong>/*selfmen.cpp*/#include <iostream>using namespace std;class egg{static egg e;int i;egg (int i): I (i) {}public:static egg* instance () {return &e;} int Val () {return i;}}; Egg egg::e = 47;int Main () {//!egg x (1); cout << egg::instance ()->val () << Endl;return 0;} </strong></span>
9.
<span style= "FONT-SIZE:18PX;" ><strong>/*depend.h*/#ifndef depend_h_#define depend_h_#include <iostream>using namespace Std;extern int X;extern int y;class initializer{static int Init_count;public:initializer () {cout << initializer () "<< Endl;if (init_count++ = = 0) {cout << "performing initialization" << endl;x = 100;y = 200;}} ~initializer () {cout << "~initializer ()" << endl;if (--init_count = 0) {cout << "performing cleanup" << Endl;}}; static initializer init; #endif </strong></span>
<span style= "FONT-SIZE:18PX;" ><strong>/*depdefs.cpp*/#include "depend.h" int x;int y;int initializer::init_count;</strong></ Span>
<span style= "FONT-SIZE:18PX;" ><strong>/*depend.cpp*/#include "depend.h" int main () {cout << "inside Main ()" << Endl;cout < < "leaving Main ()" << Endl;return 0;} </strong></span>
Three. Exercises + answers
1. Create a class with an integer array. Sets the length of an array using an unnamed enumeration variable inside the class. Adds a const int variable and initializes it in the constructor initialization expression table. Adds a static int member variable and initializes it with a specific value. Add an inline constructor and an inline (inline) type print () function to display all the values in the array and invoke the static member function within the two functions.
#include <iostream>using namespace std;class a{const int i;static int j;enum{size = 100};int Arr[size];p ublic:a (int i = 0): I (i) {for (int k = 0; k < SIZE; ++k) {Arr[k] = incr ();}}; void print () {for (int k = 0; k < SIZE; ++k) {cout << arr[k] << "";} cout << Endl << endl;cout << "j =" << incr () << Endl;} static int incr () {++j;return J;}}; int a::j = 47;int Main () {A a;a.print (); return 0;}
2. Statdest. CPP, in Main () in a different order called F (), g () to verify the constructor and destructor call order, our compiler can compile them correctly?
Modify the code so that it appears in the window
#include <fstream.h>ofstream out ("Statdest.out"), Class Obj{char c;public:obj (char c): C (c) {cout << obj::o BJ () for "<< C << Endl;} ~obj () {cout << "obj::~obj () for" << C << endl;}};o BJ A (' a '); void f () {static obj B (' B ');} void G () {static obj C (' C ');} int main () {cout << "inside Main ()" <<endl;g (); F (); cout << "Leaving Main ()" << Endl;}
Results Analysis:
(1).
(2).
The compiler can compile correctly.
3. In STATDEST.CPP, after the definition of out is changed to an extern declaration and the actual definition is placed into the definition of a (its constructor, obj, which transmits the information to out), test how our machine does the default error handling. When we run the program, make sure no other important programs are running, or our machine will get an error.
The program is interrupted, but there is no problem compiling the connection.
#include <fstream.h>extern ofstream out;class obj{char c;public:obj (char c): C (c) {out << ' obj::obj () for ' << c << Endl;} ~obj () {out << ' obj::~obj () for "<< C << endl;}};o BJ A (' a '); Ofstream out ("statdest.out"); void f () {static obj B (' B ');} void G () {static obj C (' C ');} int main () {out << ' inside main () ' <<endl;g (); F (); out << "leaving Main ()" << Endl;}
4. Create a class whose destructor displays a piece of information and then calls exit (). Create a global static object of this class to see what happens?
#include <iostream>using namespace Std;class b{static int i;public:b () {cout << "b::b ()" << Endl;} ~b () {cout << "b::~b ()" << endl;exit (0);}}; int b::i = 47;int Main () {B B;return 0;}
5. Modify the VOLATILE.CPP of chapter 7th so that COMM::ISR () runs as an interrupt service routine.
late additions.
Interrupt Service program, the processor processing "dispatch", can be understood as a service, is done by the implementation of a pre-programmed specific program to complete, this process of "dispatch" is called-Interrupt service program.
The above code is only for reference, if there are errors please point out, thank you ~
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
"C + + Programming thought" nineth chapter naming Control (knowledge points + exercises + answers)