C ++ language FAQ solution: # 54 ~ # 80

xiaoxiao2021-03-06  56

This is the traditional translation of "C frequently asked Questions" found from Taiwan http://www.cis.nctu.edu.tw/chinese/doc/research/, found "C Frequently Asked Questions" Ye Bingzhe, is also a translator of "C Programming Language" 3 / e, this article is very good, paying it for learning purposes, I didn't get the author's authorization, the copyright of the original article still belongs to the original author .c Language FAQ Q54: Derived * -> Base * is normal; what is Derived ** -> Base **? C let Derived * can transform to base * because derived objects "is a" substrate object. However, it is wrong to transform from derived ** to base **! If it is possible, Base ** may be solved (generated a base *), which may point to another "different" derivative category, which is wrong. According to this, the array of derived categories is "not a" substrate class). In PARADIGM SHIFT C training course, we used the example to be metaphor: "A bag of apples" is not a bag of fruits "." A Bag of apples is not a bag of struit. "If a bag of apples can be used as one Bag fruit to pass, others may put the banana in the apple bag! ================================= ======== Q55: The array of derivative categories "is not" the array of substrates, does it indicate that the array is not good? That's right, "Array is very bad" (joking. C built-in array has a problem that is not easy to detect. Think about: void f (base * arrayofbase) {arrayofbase [3] .memberfn ();} main () { Derived arrayofderived [10]; f (arrayofderived);} The compiler considers this is entirely safe because it is converted from Derived * to base * is normal. But in fact this is very powerful: because Derived may be more than Base The array index in the big and f () is not only no type, and it may not refer to the real object! It usually refers to the middle of a unlucky derived object. The fundamental problem is: C cannot distinguish "Point to a thing" and "point to a array". Natural, this is the characteristics of C "inherit" from the C language. Note: If we use a "category" rather than the most original array ( For example, "Array " instead of "T []"), this issue can be picked out in the compile period, not when executed.

========================== ● 12A: inherit-virtual function ================ ========== Q56: What is the "virtual member function"? The virtual function allows derived categories to "replace" the operation provided by the original base category. As long as an object is derived, even if we are a pointer to the substrate object, the compiler will still ensure that the "replaced" member function is called. This allows the base category algorithm to be replaced by the derivative, even if we don't know what the derivative category is like. Note: Derivative categories can also be "partially" substituted (override, OVERRIDE) to remove the work behavior of the substrate (if necessary, the active behavior of derivative categories can also call its base category). ================================================= q57: C how to do dynamic series And static type? In the discussion below, "PTR" refers to "pointer" or "reference". A PTR has two types: static PTR type, the type of dynamic "pointed object" (the object may actually be a PTR that is derived from other categories). "Static Typing") refers to the "legitimacy" of the call, is based on the static type of PTR, and if the PTR type can process member functions, "points to the object" Nature can also. "Dynamic Binding") refers to: "Program Code" call is based on the type of "target" pointed. A "dynamic series" is called because the program code that truly being called is dynamically (during execution period). ============================================================== Non-virtual function override (OVERRIDE)? Yes, but not good.

C vetements sometimes redefine non-virtual functions to increase efficiency (in exchange for practical practices that may be used to derivative categories), or to avoid the masking effect (Hiding rule, below, or Take a look at the ARM ["Annotated Reference Manual"] SECT.13.1), but the user's visibility effect must be identical, because the non-virtual function is the basis for dispatch (DISPATCH) with a pointer / reference. The dynamic type of the object that is referred to / referenced is determined. ================================================= q59: "Warning: Derived :: F ( INT) HIDES BASE :: F (FLOAT) What does it mean? This means: you can't die. Your question is: If Derived announced a member function called "F", Base has already announced a different type of signature type (such as: parameter type or constant), such a Base " f "will be" shaking HIDE "instead of" Multi-load OverLoad "or" override override "(even if Base" f "is already virtual). Solution: Derived wants to redefine the member function that is blocked by Base (even if it is not a virtual). Usually redefined a function, just call the appropriate Base member function, such as: class base {public: void f (int);}; class derived: public base {public: void f (double); void f (int i ) {Base :: f (i);}}; // ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ========================================================== q60: Do I have a public member function that is inherited by a base category? Absolute absolute absolute absolute never do this! It is a very common error that wants to shield (delete, undo) inherited the public member function. This is usually a stupid thing that his head is filled with paste.

====================================================== is a kind of "circle" is a kind Elliptical "Ellipse"? If the ellipse can change the size of its two axes asymmetrically, the answer is negative. For example, the ellipse has a "setsize (x, y)" operational behavior, and it guarantees that "the width () of the ellipse is x, Height () is Y." In this case, the normal circle cannot be considered an ellipse. Because as long as you make an elliptical, it is not moving, the circle is no longer an ellipse. In this way, there may be two (legitimate) relationships between circles and ellipses: * Talk completely from the ellipse. * Let the circles and ellipses are derived from a substrate, which is "unsmorled setsize operation special elliptical". In the first scheme, the ellipse can inherit from "asymmetric graphics" (with a setsize (x, y)), the circle inherits from "Symmetric Graphics" with a setsize (size) member function. In the second scenario, the oval "oval" category can be "setsize": "width ()" and "height ()" are all set to "size", then let the ellipse and round Derived in ovate. The ellipse (rather than being circular) will join a "setsize (x, y)" operation (if this "setsize ()" The name of the operation behavior is repeated, you have to pay attention to the "shielding effect") of the previously emitted. ============================================================================================================================================================================================================================================================================ Elliptical "two difficulties, is there any other statement? If you say that ellipse can be sorry, it is said that the circle is an ellipse, and it is said that the circle cannot be asymmetrically squeezed, so obvious, you have to do something. Amendment (honestly said that it will be removed). So you don't have to remove "Ellipse :: setsize (x, y)", remove the inheritance relationship between circles and ellips, is to admit that your "circular" is not necessarily a round. There are two OO / C novices to the traps that are most likely to fall.

They want to use procedures tips to make up for the differences (they redefined circle :: setsize (x, y), let it throw out an exception, call "Abort (), or select the average of two parameters, or Don't do anything), unfortunately, these skills will make users feel surprised: they originally expected "width () == x" and "Height () == y" These two facts will be established. The only reasonable approach seems to be: reducing the guarantee of elliptical "setsize (x, y) (for example, you can change:" This operation behavior "may" set width () to X, Height () Y, it is also possible "do not do anything" "). Unfortunately, this will push the boundaries, because the user does not have any meaningful object behavior is enough to rely on, the entire category is not a value, it is very different (it is hard to convince others to use one: ask you what it is doing You will only shrug your shoulders and don't know.). ========================== ● 12C: Inherit-access rules =============== =========== Q63: Why is derived category unable to access the "private" thing of the substrate? Let you not be influenced by the change in the base category. The derivative category cannot access the private member of the substrate, which effectively derivates the derivative category "seal", private members within the substrate category change, nor does it affect the derived category. ================================================= q64: "public:", "private:" PRIVATE: "," Protected: "is the difference? "Private:" I discussed in the previous few sections; "public:" means: "Anyone can access it"; the third "protected:" is a member (information member or member function) only Can be accessed by derivative categories. [Translation] "Protected" is the "derivative category" instead of the "Derivative Class Object Case" to access part of Protected.

================================================= q65: When I changed the interior, How to avoid the subcategory destruction? The object category has two different interfaces, providing different types of users: * "public:" interface is used to serve the discretion. * "protected:" The interface is used to serve the derived category. Unless you expect that all subcategories will be built by your work, you should put the base category of data bit in "Private:", with "protected:" to access functions within the line to access those data. In this case, even if the private information of the base category changes, the derivative category does not scrap unless you change the access function at the substrate category. ================================= ● 12d: inheritance - Construction sub-and deconstruction ======= ========================================================================================================== q66: Be called? During the construction of the base category base, the object is not derived from derived, so if "base :: base ()" calls the virtual function "Virt ()", "Base :: virt ()" Call, even if there is "Derived :: Virt ()". Similar truth, when the base is executed, the object is no longer a derived, so when Base :: ~ base () call "Virt ()", "Base :: Virt ()" will be executed, and Non-covered versions "Derived :: Virt ()". When you imagine: If "Derived :: Virt ()" encounters a member of the Derived category, what is the disaster, you will soon see the wise place of this rule. ================================ Q67: derived class destructor should be explicit destructor call the base do? Don't, you must not show the consolences ("absolutely don't do it").

Derivative category deconstruction (whether you are obviously defined) will "automatically" automatically "to call the deconsive sub-object of the member object, and the sub-category of the base category. Members object will decons in their opposite sequence in their category, followed by sub-objects of the substrate category to deconate them in the opposite order of the category base list. Only in extremely special cases, you should call the monoconic, like: Deconstructing an object that is configured by the "new NEW Operations". ==================================================== ● 12e: inherit -Private Inherited with protected ==================================================== q68: What should I? Express "private inheritance? Use ": private": public. "Such as: class foo: private bar {//...} ;======================= ========= Q69: How much is "private inheritance" and "成 om"? Private inheritance is a grammar deformation of "kettle" (HAS-A). Such as: "Car Has-a Engine" ("Car Has-a Engine") Relational ingredients can be expressed: class engines {public: engine (int Numcylinders); void start (); // starts this engine}; class car {public: Car (): E_ (8) {} // Initializes this car with 8 cylindersvoid start () {e_.start ();} // start this car by starting its engineprivate: Engine E_;}; same "HAS-A "The relationship can also be expressed by private inheritance: Class Car: private engine {public: car (): Engine (8) {} // initializes this car with 8 cylindersngine :: start; // start this car by starting its engine}; These two types of ingredients have a spiral similarity: * Under these two cases, CAR contains only one engine member object. * The two cases cannot be made (outside) users by car * to engine *. There are also a few different points: * If you want to let each car contain several engine, you have to use the first pattern.

* The second type may result in unnecessary multiple inheritances. * The second type allows members to be converted from car * to Engine *. * The second type can be accessed to the "protected" member of the base category. * The second type allows CAR to overwrite the virtual function of the ENGINE. Note: Private inheritance is usually used to get access to the base category "protected:", but this is usually just a short-range solution. ======================================================== Which one is? Ingredients or private inheritance? Ingredients. Under normal circumstances, you don't want to access the inside of too many other categories, but private inheritance will give you extra power (and responsibility). However, private inheritance is not a flood beast; it is just a lot of flowers to maintain, because it adds others to your things, let your program out the opportunity. The timing of using private inheritance is: When you want to create a new Fred category, it will use the Wilma class program code, and Wilma's program code will call to your Fred category. Under this situation, Fred calls Wilma's non-virtual function, Wilma also calls its own virtual function (usually a pure virtual function) overwritten by Fred (usually a pure virtual function). It is too difficult to use ingredients. class Wilma {protected: void fredCallsWilma () {cout << "Wilma :: fredCallsWilma () / n"; wilmaCallsFred ();} virtual void wilmaCallsFred () = 0;}; class Fred: private Wilma {public: void barney ( ) {cout << "Fred :: barney () / n"; wilma :: fredcallswilma ();} protected: virtual void wilmacallsfred () {cout << "fred :: wilmacallsfred () / n";}}; = ================================================ q71: I should use the pointer to the way, " Private "derivative category transferred to its substrate? Of course, it should not. From the private derivative category of operation, partners, from the relationship between the base category, it is known from Privatelyder * to Base * (or from Privatelyder & to Base &) is safe; forced transformation It doesn't matter if you don't need it. However, people with Privateer should avoid this unsafe conversion, because this is based on Privateder's "Private" decision, this decision is easy to change in the future.

======================================== q72: protected inheritance and private What is it inherited? Similarly: Both can cover the virtual function of private / protect the base category, both of which do not treat derived categories as "a" base category. Not analog: Protection inheritance can let the derivative category know its inheritance relationship (show the implementation details). It is advantageous (allowing subcategories for protecting inheritance categories, using this relationship to use protection base categories), and cost (protective inheritance categories, unable to change this relationship, but not destroying further derivative categories). Protection inheritance uses ": protected" Syntax: Class Car: protected eNGINE {//...} ;========================== ============== Q73: "Private" and "protected" access rules? Take this category as an example: Class B {/ *..}; Class d_priv: private b {/*...*/}; Class D_Prot: protected b {/*...*/}; Class D_Publ: public b {/*...*/}; class userclass {b b; /*...*/}; no subcategory can access B's private part. In D_Priv, B's public and protected part becomes "private". In D_PROT, B's public and protected part are "protected". In D_Publ, B PUBLIC Site or PUBLIC, PROTECTED or Protected (D_Publ IS-A-Kind-Of-A B). Class "UserClass" can only access B PUBLIC parts, that is, seal UserClass from B. To turn B Publicone in D_Priv or D_PROT, it will also become public, as long as "B ::" is added in front of the name of the member.

For example, if you want "b :: f, float" member in D_PROT is also public, write this: Class D_PROT: protected b {public: b :: f; // Note: Not Write "B :: f (int, float)}; ====================================== ■ □ 13: Abstract =============================================== q74: Separate Interface What is the use of doctors? The interface is the most valuable resource of the company. The design interface will consume more than only a bunch of independent categories, especially: the interface needs to spend more advanced manpower. Since the interface is so important, it should be protected to avoid the impact of the data structure and the like. So you should separate the interface from the actual. ========================================================= in C , how should I separate? Interface with practical (like MODULA-2)? Use ABC (see next to FAQ). ================================================== q76: ABC ("Abstract base class") What is it? At the design level, ABC corresponds to the abstract concept. If you ask the mechanic to say that he repaires the transportation tool, he may guess your mind is "which" transportation tool, he may not repair space shuttle, ship, bicycle, and nuclear submarine. The problem is that "Transport Tools" is an abstract concept (such as: You can't built a "transport tool" unless you know what to build "). In C , the transportation tool category can be used as an ABC, while the bicycle, space shuttle ..., etc., is a "transportation tool). In OOP in the real world, ABC is everywhere.

At the program language level, ABC is a category of a pure virtual member function (see next to FAQ), you cannot build an object for an ABC (case). =============================================== Purif, Pue Virtual What is the member function? ABC's member function, you can only do it in derived categories. Some member functions are only existed in the concept, without any substance definition. For example, suppose I want you to draw a shape, it is located in (x, y), size is 7. You will ask me "Which Shape?" I should draw? "There are different paintings.) In C , we can first mark a" DRAW () "such Operating behavior, and specify that it can only be (logically) defined in the subcategory: Class Shape {public: Virtual Void Draw () const = 0; // ... ^^^ --- "= 0" means: It is "Pure Virtual"}; this pure virtual function allows "shape" into an ABC. If you like, you can use the "= 0" syntax to be: The program code is located at the NULL pointer. Therefore, "Shape" provides a service item, but it is now unable to provide a substantial program code to achieve it. This will ensure that any [specific] class object derived from Shape, "will" have the member function we prior in advance, even if the base category does not have enough information to real "definition" it.

[Translation] "Definition" here, "Declaration", two words to distinguish! ================================================= q78: How to provide printing for the entire class class Features? Provide a Friend Operator << Call Protected virtual function: Class base {public: Friend Ostream & Operator << (Ostream & O, Const Base & B) {B.Print (O); Return O;} // ... protected: Virtual Void Print (Ostream & O) const; // or "= 0;" If "Base" is an abc}; Class Derived: Public Base {Protected: Virtual Void Print (Ostream & O) Const;}; Son of All Base Categories only need their own "Print (Ostream & Const" member function (they share "<<" Operator). This tip makes the partnerships have a dynamic skill. ================================================= q79: When should the decoction make Virtual? When you might go to "Delete" by a pointer to the substrate. The virtual function takes the program code attached to the truly category belonging to the object, not the program attached to the pointer / reference itself. When you say "delete baseptr", and its substrate has a virtual deconed man, the deconstructed subsequent subsection that is really called, is the deconed man belonging to the style of the Baseptr object, not the pointer itself Deconstructure. Generally speaking, this is indeed a good thing. Let you feel convenient, the only thing you don't have to set a category of deconstruction as Virtual is: "This category" does not have "any virtual function". Because the first virtual function is added, additional space burden is added to each object (usually a size of a machine Word), which is the secret of the compiler to perform dynamic series; it usually replaces each object Add additional pointers, called the "Virtual Table Pointer" or "VPTR".

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

New Post(0)