[23] Inherited - you don't know (Part of C FAQ Lite, Copyright © 1991-2001, Marshall Cline, Cline@parashift.com)
体,, nicrosoft @ sunistudio.com (East day production room, East day document)
FAQS in section [23]:
[23.1] Is the non-virtual function of the base class call the virtual function? [23.2] The FAQ above made me confused. Is that another policy using a virtual function? [23.3] When the base class constructor calls the virtual function, why do not call the virtual function to rewrite the virtual function? [23.4] Delicious class can reset ("overlay") the non-virtual function of the base class? [23.5] "Warning: Derived :: F (FLOAT) HIDES BASE :: F (int)" What does it mean? [23.6] "Virtual Table" is an unresolved external in what does it mean?
[23.1] Is the non-virtual function of the base class call the virtual function?
[Recently Created (on 4/01). Click Here to Go To The Next FAQ in The "Chain" of Recent Changes
]
can. Sometimes (not always!) This is a good idea. For example, suppose all Shape objects have a public print algorithm. However, this algorithm relies on their area and they have different ways to calculate the area. In this case, Shape's Area () method (translation: Member function of the Shape area) must be Virtual (may be pure-virtual), but shape :: print () can be in Shape The premise is that all derived classes do not require different printed algorithms.
#include "shape.hpp" Void Shape :: Print () const {float a = this-> area ();
// area () is pure
// ...
}
[TOP | BOTTOM | Previous Section | Next Section]
[23.2] The FAQ above made me confused. Is that another policy using a virtual function?
[Recently Created (on 4/01). Click Here to Go To The Next FAQ in The "Chain" of Recent Changes
]
Yes, it is a different strategy. Yes, that is indeed two different basic methods using virtual functions:
Suppose you have encountered the situation described in the previous FAQ: Every derived class has a structure, only one small piece of different methods. Therefore, the algorithm is the same, but substantially different. In this case, you'd better write a comprehensive algorithm in the base class as a public: method (sometimes non-virtual), then write different small pieces in the derived class. This small piece is declared in the base class (usually protected:, of course, at least Virtual), and finally defined in each derived class. The most important problem in this case is the public: method of the comprehensive algorithm: method should be Virtual. The answer is that if you think some derived classes may need to overwrite it, let it become Virtual. Suppose you have encountered the opposite of the previous FAQ, each derived class has a structure completely different, but most of the small pieces (if not all, if not all) the same approach. In this case, you'd better put a comprehensive algorithm in the public: Virtual defined in the derived class, and put a small piece of public code (avoid code repetition) hide somewhere (Anywhere!). Generally placed in the base class Protected: part, but not necessarily, it may not be the best. Find a place to hide them. Note that due to public: Users don't need to do what they do, if they hide them in the base class, they should usually make them protected: Assume that they are protected:, then it may not be Virtual: If the derived class does not like one of them, it is not necessary to call this method. Emphasize that "there is / again" in the above list, rather than "two choices". In other words, on any given class, it is not necessary to select in both strategies. There is only one method F () that meets the policy # 1, and there is a method G () that meets the policy # 2 method G () is very normal. In other words, in the same class, there are two strategies to work very normal.
[TOP | BOTTOM | Previous Section | Next Section]
[23.3] When the base class constructor calls the virtual function, why do not call the virtual function to rewrite the virtual function?
When the base class is constructed, the object is not an object of a derived class, so if Base :: base () calls the virtual function Virt (), base :: virt () will be called, even if Derived :: Virt () (Translation: The virtual function that is derived) exists. Similarly, when the base class is destructed, the object is no longer a derived class object, so if Base :: ~ base () calls Virt (), base :: var () is controlled, not heavy Written Derived :: Virt (). When you can imagine if Derived :: Virt () involves a disaster caused by a member of the derived class, you can see the wise to see this method. In detail, if Base :: base () calls the virtual function Virt (), this rule makes Base :: Virt () called. If not followed by this rule, Derived :: Virt () will be called before the derived object's derived part is constructed, and a member object that belongs to the derived object is not constructed, and derived :: virt () But you can access it. This will be a disaster.
[TOP | BOTTOM | Previous Section | Next Section]
[23.4] Delicious class can reset ("overlay") the non-virtual function of the base class? Legal but unreasonable.
Experienced C programmers sometimes redefine the non-virtual function (for example, the implementation of the derived class can be more efficiently utilizing the resource of the derived class), or to avoid hidden rules. Even if the non-virtual function is based on the dynamic type of the pointer / reference, the customer's visibility must be consistent, but its customer visibility must be consistent.
[TOP | BOTTOM | Previous Section | Next Section]
[23.5] "Warning: Derived :: F (FLOAT) HIDES BASE :: F (int)" What does it mean?
Means: You have to finish.
What you have is: If the base class declares a member function f (int), and the derived class declares a member function f (FLOAT) (the name is the same, but the parameter type and / or quantity is different), then Base's F (int) Hidden instead of being overloaded or overridden (even if F (int) of the base class is virtual)
Here is how you get rid of your dilemma: Derived class must have a USING statement that is hidden member functions, for example:
Class base {public: void f (int);}; class derived: public base {public: using base :: f;
// this un-hides base :: f (int)
Void f (double);
If your compiler does not support using syntax, then redefine the hidden member functions of the base class, even if they are not empty. Generally speaking, this redefine is only used :: syntax calls the base class hidden member functions, such as
Class Derived: Public Base {public: Void F (Double); Void F (INT i) {base :: f (i);}
// The redinition merely calls base :: f (int)
}
[TOP | BOTTOM | Previous Section | Next Section]
[23.6] "Virtual Table" is an unresolved external in what does it mean?
If you get a connection error "error: unresolved or undefined Symbols detected: Virtual Table for class fred", it may be that you have an undefined virtual member function in the Fred class. The compiler typically creates a magical data structure called "virtual function table" (this is how it handles dynamic binding). Usually you don't have to know it at all. But if you forget to define a virtual function for the Fred class, you sometimes get this connection error. Many compilers put this incredible "virtual function table" into the editing unit of the first non-inner built-in function of the class. So if the first non-inner built-in function of the Fred class is wilma (), the compiler places the fred virtual function table in the editing unit where Fred :: Wilma () is located. Unfortunately if you accidentally forgot to define fred :: wilma (), then you will get a "Fred's Virtual Table Is undefined" error rather than "Fred :: Wilma () IS Undefined "(Fred :: Wilma () is undefined). [TOP | BOTTOM | Previous Section | Next Section]
E-mail the author [C FAQ Lite | Table of Contents | Subject Index | About The Author | © | Download Your Own Copy] Revised Apr 8, 2001