"MODERN C ++ Design" LOKI library reading 3: more inherited improvement

zhaozj2021-02-16  56

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 , r>

: 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 :: visit; // is a pure virtual function, inevitably realized in the final class

}

// WQ This is the end point of recursive.

Template

Class Visitor , r>: public 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 Class BasevisitorIMPL;

Template

Class BasevisitorImpl , r>

: 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 :: Visit;

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 , r>

: 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 . If there is inheritance between multiple types in TypeList, since its actual base class is Visitor , inheritance // Relationship is isolated, there is no "diamond defect".

// Class Template BasevisItem

Template

Struct defaultcatchall

{

Static R Onunknownvisitor (Visited &, Basevisitor &)

{RETURN R ();

}

// Class Template BasevisItem

Template

<

TypenAme R = Void,

Template class catchall = defaultcatchall

>

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 (& guest))

// 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 * P = Dynamic_Cast *> (& Guest))

{// 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 :: OnunkNownVisitor (visited, guest);

}

}

// 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 :: Visit;

Template

Returntype genericvisit (visited & host)

{

Visitor & Subobj = * this;

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);

转载请注明原文地址:https://www.9cbs.com/read-26714.html

New Post(0)