Three: Static (Static) Several typical applications:
The role of Menu (Menu Hank)
Everyone knows if the program is to be, to directly initialize the variables in the category defined, and use the night-to-night compiler can only use menu to achieve this effect, the code is like this:
Class Print
{
Menu {count = 10}; // Get an initial value by enumerating
String info [count];
}
The process of writing process code with the MFC should know this feature, which is the IDD in the initialization class through the MENU and then uses the code generated by a piece of MFC.
///
Class Capestdlg: Public CDialog
{
PUBLIC:
// ...... Definition of other member functions and constructor
// Dialog Box Data
Enum {IDD = IDD_ACETEST_DIALOG}; // Use MENU directly to initialize IDD, IDD_ACETEST_DIALOG is the id value of the dialog
// ...... Definition of other member functions.
}
// Implement file
// ......
Cacestdlg :: Cacestdlg (CWND * PParent / * = null * /)
: Cdialog (CACETSTDLG :: Idd, PParent) // Note: Use IDD initialization base class directly here.
{
m_hicon = AFXGetApp () -> loadicon (iDR_mainframe);
}
// ......
The above direct initial and useful features are implemented by means of MENU. But this is a bad thing to make Menu have lost the original role here (the function of Menu itself is not reflected) But after STATIC can use Static constant to achieve the same effect, because a class Static constants are treated as a constant time, and because the static has an internal connection of the file scope, there is no conflict of repeated definitions. The code example has been given when the static member variable (object) is introduced.
I don't know if you have a note, MENU can only use integers, but the internal static constants can be any type, even hug user custom types.
2. Single piece mode
Everyone knows the single-piece mode. If you are not familiar with the book that can refer to the assessment mode, the single mode guarantees that only one instance is exist, the specific member variable and the static member function and the access level of the class. Really, the specific code is as follows:
//
Class singleton {
PUBLIC:
Static Singleton * instance (); // Note: Static member function returns an instance of the class
Virtual ~ Singleton () {};
protected:
SINGLETON () {};
Private:
Static singleleton * _instance; // Note: A static member variable pointing to the instance of a class
}
// Implement the file:
Singleton * singleton :: _ instance = 0; // Static member variable initialization
Singleton * Singleton :: Instance () // Returns a static pointer to the class instance
{
IF (_Instance == 0)
_INSTANCE = New Singleton;
Return_INSTANCE;
}
/
The static member function adds a static member variable to realize single-piece mode, where static member function controls the instance of the return class, because the static member function cannot be a virtual function, so the subclasses can not be redefined to it, this is guaranteed You can only use this interface to use the class. With a static member variable to point to that uniquely instantiated object, of course, the most implementation is initialized to 0, and then the establishment of the inert initialization timing instance,
If you replace these static objects and global static functions, it is believed that there will be many problems with J.3. Eliminate global data
Everyone knows that everyone knows that the introduction of global data is really solving some tricky problems when appropriate, but the global data is a cross-file scope, so that the correct initial initial initial in some cases is very difficult (next 4 points) It will be said that once the global variable is established, it is quite difficult to eliminate it. As the "namespace pollution" problem is, but the global variable is bound to the variable (object) and the algorithm code, making complex It is quite difficult to use.
These problems existing for global variables can be optimized by using packaged static access.
First put the global variable into a class or structure
Then privatize them and add a static member function access interface.
For example, there is a global variable below
BOOL g_flag;
INT g_size;
Const char * in_modulename;
For these global variables, the method described above is improved, which can produce the following code:
Class Global
{
Private:
Static bool s_flag_;
Static int S_SIZE_;
STATIC const char * s_in_modulename_;
Private:
Global (); // Private constructor makes the class not instantiate
// .... Other related functions
PUBLIC:
// Deposit the correlation value
Static void setflag (BOOL flag) {s_flag_ = flag;}
Static void setsize (int size) {s_size_ = size;}
Static void setINModulenAme (const char * in_modulename) {s_in_modulename_ = in_modulename;}
// Get the correlation value
Static int getflag () {return s_flag_;}
Static int getSize () {return s_size_;}
Static const char * getinmodulename () {return s_in_modulename_;}
}
It is believed that this reconstruction method can solve the global problem by introducing access to a class package and a static member function. It should be a better way.
4. Solve initial interdependence
If you let the object A must initialize before the object B, but also let A initialization depend on B has been initialized, the same A, B is in different compilation units, this is what we can't control the correct initialization order, solution Still (note, the following examples of "Think In C " are referred to, because it is a summary, copying, no problem, J),
At this time we can use Jerry Schwarz to create an I O S T R E a M library (because C i n, C O U T and C E R R is defined in different files). This technology requires an additional class in the library header file. This class is responsible for the dynamic initialization of static objects in the library. Here is a simple example:
//Depend.h - static initialization technique
#ifndef depend_h_
#define depend_h_
#include
Extern Int X; // degiarations, Not Definitions
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 = 100;
}
}
~ Initializer () {
Cout << "~ initializer ()" << endl;
IF (- init_count == 0) {
Cout << "Performing Cleanup" << Endl;
}
}
}
// the folowing creates one Object in Each
// file where depend.h is included, but this
// Object is Only Visible forin That File:
STATIC INITIAL INIT;
#ENDIF // depend_h_
X, y's statement only indicates the existence of these objects, and does not assign storage space for them. However, Initializer Init is defined for each file that contains those objects containing this header file, because the name is static (here control visibility rather than specifying storage type, because the default is within the file range) It is only in the file The compilation unit is visible, so the connector does not report a multi-definition error.
Below is a file that contains x, y, and init_count definition:
//:Depdefs.cpp--definition
#include "depend.h"
// Static Initialization Will Force
// all these values to zero:
INT X;
Int Y;
INT INTIALIZER :: init_count;
(Of course, the init static instance of a file is also placed in this file) hypothesis that the user has two other files:
//:Depend.cpp-static initialization
#include "depend.h"
with
//:Depend2.cpp-static initialization
#include "depend.h"
int main ()
{
Cout << "Inside main ()" << endl;
Cout << "Leaving main ()" << endl;
Return 0;
}
Now which compile unit is initialized to initialize. When the compilation unit containing Depend.h is initialized, the init_count is zero, and the initialization is completed (this is due to the internal type of global variables being set to zero before dynamic initialization). For the rest of the compilation unit, initialization will jump over. Clear the reverse order, and ~ initializer () ensures that it only occurs once. This example uses internal types as global static objects, which can also be used for classes, but their objects must be initialized with Initializer. One way is to create a class without constructing functions and destructuring functions, but initialize and clear this class with member functions of different names. Of course, more common practice is to set the pointer to the object in the initializer () function, and create them dynamically in the heap.
Note: Because it is a summary, it will be convenient for himself. The last point is directly taken from "Think In C ". I think this example is very good! So I have taken it directly :)