LOKI library reading 3: more inherited improvement
Many inheritance, always being associated with Goto. Logically, they are all language must be part of the language, but they are in theory that they can not be used at all. Such a "holy strip" has been form: do not use them as much as possible. And even have been shown to be "absolutely do not use them."
In the "Development Process Debug Technology" of Steve MAGUIRE, it is pointed out where you can safely use GOTO. In the Loki library, it also pointed out more inherited safe use.
Almost only C supports multiple inheritance, not more, but because no "interface" is supported. OO should be programmed to program, and C is used as a strict compile period check language, and it is scheduled to "program the type". This defects are required to redeem more inheritance and templates.
Multi-inheritance happens is mainly "rhombic defect", and "THIS pointer value jump".
The "THIS pointer" is mainly created by the "object identity". You can see "Exceptional C " Item 38, C only specifies that the same address points to the same object, and the address is different from that any problem, so use the address "identity" judgment is the error behavior (mostly most In case it is available), more inherits should not be assigned.
Use "virtual base classes" to solve "diamond defect" is made more complicated. First, "inherit" should be "inherited" with the original face: inheritance is not achieved, but to get the interface. So, "More Effective C " Item 33, "Designed non-tail classes as abstract classes." But these non-end abstract classes are generally quasi-physical classes. To use multiple inherits safely, only one base class is quasi-entity class, and other base classes must be pure interface classes. These pure interface classes are defined in "Modern C Design" to mainly play the role of "policy class", and call "Policy-based programming". With regard to "policy programming", there is still a paper on the "Extreme Programming Research" that can be downloaded to the original book, and "Extreme Programming Research", so I don't talk much.
Multi-inheritance in the Loki library rely on Typelist, reassenced with two inheritance, and it will be clear in the following Visitor source code. The first reaction is: Very like design mode "appearance mode". In actual use, of course, the difference is far away. I have been using the card shell for a long time, until now, still can't run, it seems that I can only study it again. Everyone will be shocked to this usage, all I will annotate the source code of the next posted hierarchygeerators.h for everyone to brainstorm.
Take the source code of the Visitor mode in a sense as an example, explaining the "precise down type mapping" leaving in the second:
// Class Template Basevisitor
// the base class of any acyclic visitor
Class Basevisitor
{
PUBLIC:
Virtual ~ basevisitor () {} // wq Note: There is no VISIT method, all isolated loop dependence.
}
// Class Template Visitor
// The building block of Acyclic Visitor
Template
Class Visitor
{
PUBLIC:
Typedef r retturntype;
Virtual Returntype Visit (T &) = 0; // WQ Note: This function seems to be inoperable, but it is crucial
// If you draw a inheritance, let it put it in, you can see it very clearly.
}
// Class Template Visitor (Specialization)
// this specialization is not present in the book. It makes it easier to define
// Visitors for multiple type in a shot by using a type elEList. EXAMPLE:
// // WQ Note: This is a typical use, please experience more.
// Class Somevisitor:
// public basevisitor // Required
// public visitor
// public visitor
// {
// public:
// Void Visit (RasterBitmap &); // Visit A RasterBitmap
// void visit (paragraph &); // visit a paragraph
//};
// WQ Note: It is the offset of the front Visitor. It can independently form cycle-dependent Visitor mode.
Template
Class Visitor
: Public Visitor
, Public Visitor{// wq Note, I want to draw a recursive inheritance map, the vision map is too trouble, please draw it yourself.
PUBLIC:
Typedef r retturntype;
// Using visitor
:: visit; // WQ Note: No need required, because all Visit methods// Using visitor
}
// WQ This is the end point of recursive.
Template
Class Visitor
{
PUBLIC:
Typedef r retturntype;
Using visitor
:: visit;}
// Class Template BasevisitorImpl
// Implements Non-Strict Visitation (you can IMPLEMENT Only Part of The Visit)
// functions
// WQ Note: This is another Visitor version with the default implementation.
Template
Template
Class BasevisitorImpl
: Public Visitor
, Public BasevisitorImpl
{// wq Note, I want to draw a recursive inheritance map, the vision map is too trouble, please draw it yourself. PUBLIC:
// Using BasevisitorImpl
Virtual R Viisit (HEAD &) / / WQ Note: is Override for the Visit method for Visitor
{RETURN R ();} // WQ Note: r () is set up for VoID!
}
Template
Class BasevisitorImpl
: Public Visitor
{
PUBLIC:
Virtual R Visit (HEAD &)
{RETURN R ();
}
// WQ Note: As shown in the typical usage, the ultimate Visitor entity is inherited from Basevisitor and Visiotr
// Class Template BasevisItem
Template
Struct defaultcatchall
{
Static R Onunknownvisitor (Visited &, Basevisitor &)
{RETURN R ();
}
// Class Template BasevisItem
Template
<
TypenAme R = Void,
Template
>
Class BasevisIke
{
PUBLIC:
Typedef r retturntype;
Virtual ~ basevisitable () {}
Virtual Returntype Accept (Basevisitor &) = 0;
protected: // Give Access Only to the hierarchy
Template
Static Returntype AcceptiMPL (T & Visited, Basevisitor & Guest)
{
// WQ Note: This is the so-called "precise down type mapping"
// Traditional Visitor implementation, the following statement is: if (t * p = dynamic_cast
// If there is inheritance relationship between multiple HOST, T and its derived classes can be established, and the conversion is inaccurate.
// Now, only the precise T type can be set up.
// Apply the Acyclic Visitor
// WQ Note: Traditional Visitor is inevitably a pass RTTI plus IF judgment. Now, due to the use of
// The automatic type of template is derived, no need to hardcode the type, so the loop dependence is cut!
IF (Visitor
{// WQ Note: In C , in For, IF, and WHILE () can also declare the variable, // and the survival period is only the end of this statement. This example is to the downward "}".
Return P-> Visit (Visited);
}
Return Catchall
}
}
// macro define_visitable
// Put IT in Every Class That You Want to Make Visitable (in Addition TO
// deeriving it from basevisitable
#define define_visitable () /
Virtual Returntype Accept (Basevisitor & Guest) /
{RETURN AcceptImpl (* this, guest);
// Class Template CyclicVisitor
// Put IT in Every Class That You Want to Make Visitable (in Addition TO
// deeriving it from basevisitable
Template
Class Cyclicvisitor: Public Visitor
{
PUBLIC:
Typedef r retturntype;
// Using visitor
Template
Returntype genericvisit (visited & host)
{
Visitor
Return Subobj.visit (Host);
}
}
// macro define_cyclic_visitable
// put it in every class thing you want to make visitable by a cyclic visitor
#define define_cyclic_visitable (somevisitor) /
Virtual Somevisitor :: Returntype Accept (Somevisitor & Guest) /
{Return Guest.GenericVisit (* this);