Dynamic Implementation Technology of MFC abstract classes
Not long ago, I asked the same question on the BBS of Peking University and Harbin Institute of Technology, "Can an abstract class be instantiated? Not sure?". A few days later, I got answers from prawns, and I also discussed some of them in depth, write this article to free people with the same problems from distress.
As we all know, classes that contain pure virtual functions or constructors declared as protected are called abstract classes.
The beginner must come to the following conclusion in the textbook: "Remember: The abstract class cannot be instantiated ."
There are exceptions.
// In XX. h
Class OBJ
{
Protected: OBJ ();
// Something else
Friend OBJ * createobj (); // use static. MFC uses static.
};
// In XX. cpp
OBJ: OBJ ()
{Cout <"A obj is being created" <Endl;
}
OBJ * createobj ()
{Return New OBJ ();}
// In test. cpp
Void main ()
{
OBJ * PTR = createobj ();
Delete PTR;
}
The result is as follows:
A obj is being created
Press any key to continue
It seems that the instance is successful. Of course, this example is different from dynamic creation. Let's take a look at how MFC is dynamically created (I wonder if you find out, in the SDI and MDI programs of MFC, both use the dynamic creation mechanism, but he uses some macros and cruntimeclass to help)
Hou Jie explained this in detail in his "getting down to MFC", but he did not mention that one of Microsoft's goals for implementing this practice is the implementation of abstract class instantiation.
The implementation process is roughly as follows: MFC uses some macros declare_dyncreate and implement_dyncreate to quietly insert some major things into dynamically generated classes. We take the dynamic generation of SDI cmainframe as an example, take a look at the cmainframe declaration file. Its constuctor is protected, and declare_dyncreate is in mainfrm. h adds several important functions, which are crucial for dynamic creation.
Static cobject * Pascal Createobject (); // It is used to call cmainframe
Static const afx_data cruntimeclass classcmainframe; constuctor
Let's look at his implementation:
Cobject * Pascal Createobject ()
{Return New cmainframe ;}
However, in the source code, we don't seem to see anyone calling this function. In fact, Microsoft secretly transferred it to the cruntimeclass structure.
Look at the cruntimeclass Structure
Struct cruntimeclass
{
// Attributes
// Somethingelse
Cobject * (Pascal * m_pfncreateobject )();
//.....
// Operations
Cobject * Createobject ();
//...........
};
Here I only list two members related to dynamic creation.
The implement_dyncreate macro completes the initialization of cruntimeclass classcmainframe in the cmainframe class. See the following code.
# Define implement_dyncreate (class_name, base_class_name )/
Cobject * Pascal class_name: Createobject ()/
{Return New class_name ;}/
Implement_runtimeclass (class_name, base_class_name, 0 xFFFF ,/
Class_name: Createobject)
M_pfncreateobject is assigned a value of cmainframe: Createobject. You can see that the portal is correct.
Let's take a look at the implementation of cobject * cruntimeclass: Createobject.
Cobject * cruntimeclass: Createobject ()
{
.........
Return (* m_pfncreateobject )();
}
You may be confused, but you do not know about the Startup Process of the SDI program. By default, a single document file is opened when it is started. The Calling sequence is as follows:
Cwinapp: onfilenew () ---> csingledoctemplate: opendocumentfile () -->... cdoctemplate: createnewframe ()
The implementation of cdoctemplate: createnewframe () is as follows:
Cdoctemplate: createnewframe ()
{//......
Cframewnd * pframe = (cframewnd *) m_pframeclass-> Createobject ();
//....
}
M_pframeclass is the pointer to the cmainframe member cruntimeclass classcmainframe,
The following is a clear idea from the back to the front:
M_pframeclass-> Createobject () returns (* m_pfncreateobject) (), while the latter points to static cmainframe: cobject * Pascal Createobject ();
Now everything is clear.