Virtual functions (virtual keyword) and polymorphism one: A pointer problem in inheritance.
1. A pointer to a base class can point to a derived class object. When a base class pointer points to a derived class object, the pointer can only access those members of the derived object that inherit from the base class, and cannot access the elements that are unique to the subclass, unless the coercion type conversion is applied, such as a base class B and a subclass d derived from B, then B *p; D DD; p=ⅆ is OK, the pointer p can only access members derived from the base class, and cannot access members that are specific to the derived class D. Because the base class does not know these members in the derived class.
2. The derived class pointer cannot be directed to a base class object.
3. If a member variable or function in a base class is overridden in a derived class, the base class pointer can only access a member variable or function in the base class when declaring that a base class pointer is pointing to a derived class object. For example: both base class B and derived class D define function f, then B *p; D m; p=&m; M.F () calls the function f () in the base class without invoking the function f () in the derived class.
4. If the base class pointer points to a derived class object, when it is added or subtracted, it points to the next object of the base class that it considers, rather than to the next object of the derived class, so it should be considered invalid to add or subtract to the pointer.
Two: virtual function 1. Why use virtual functions: As mentioned at 1th and 3 above, when you declare a base class pointer to a derived class object, the base class pointer can access only the member functions in the base class, and you cannot access the member variables or functions that are unique in the derived class. If you use a virtual function, you can make the base class pointer to the derived class object access the member functions in the derived class. Instead of a member function in a base class, this member function in a derived class must be identical to the form of a virtual function in the base class, or the base class pointer cannot find this member function in the derived class. Using virtual functions implements an interface with a variety of methods.
2. Note You cannot declare a member variable to be virtual, meaning that the virtual keyword cannot be used in front of the member variable.
3. As described above, you should generally use a base class pointer to invoke a virtual function, and if you use the dot operator to invoke a virtual function, you lose its meaning.
4. If the base class contains a virtual function, when a pointer to a base class is declared, when the base class pointer points to a different derived class, it invokes the version of the virtual function that is defined in the corresponding derived class. This invocation method is determined at run time, for example, when a virtual function is declared in Class B, and the c,d,e inherits from B and implements its own version of the virtual function, when a pointer p of class B is defined, the virtual function defined in subclass C is called when P points to subclass C. When P points to subclass D, the virtual function defined in subclass D is called, and the virtual function defined in subclass E is called when P points to subclass E.
5. Virtual functions must be declared in the base class with the virtual keyword, or you can define a virtual function in the base class and redefine it in one or more child classes. When you redefine a virtual function, you do not need to use the virtual keyword, and of course you can continue to mark the virtual word for a better understanding of the program.
6. Classes that include virtual functions are called polymorphic classes. C + + uses virtual functions to support polymorphism.
7. When you redefine a virtual function in a subclass, the virtual function must have the exact same parameter type and quantity as the declaration of the base class virtual function, which is different from the overload. If it is not the same, then the function overload loses the essence of the virtual function.
8. A virtual function cannot be a friend of a class that declares it, it must be a member function of the class that declares it, but a virtual function can be a friend of another class.
9. Once a function is declared as a virtual function, no matter how many layers it inherits, it is a virtual function, such as D and B inheritance, and e inherits from D, then the virtual function declared in B is still a virtual function in Class E.
10. Hide virtual functions: If the base class defines a virtual function, in a derived class, however, the overloaded board of a virtual function is defined, and this version of the derived class hides the virtual function of the base class, and when you call the function using the base class pointer, you can only call the base class's virtual function, not the overloaded version of the derived class. An error occurs when a virtual function of a base class is invoked with an object of a derived class, because the virtual function of the base class is hidden by the overloaded version of the derived class.
11. virtual function with default parameters: When a virtual function of a base class has a default parameter, the redefinition of the base class virtual function must also have the same number of parameters in the derived class. However, a formal parameter can have either a default value or not, or an overload of a virtual function on a base class if the number of formal parameters in the derived class is not as large as in the base class. A redefinition of a virtual function also means that the virtual function version in the base class is called when the virtual function is called with a base class pointer to a derived class. For example, the base class defines virtual void f (int i=1, int j=2) {} A function f with two formal parameters must be defined in the derived class to redefine the virtual function F of the base class, otherwise it is an overloaded version of function f, such as void f () defined in the derived class, void f (int i), void f (int i=2) is an overload of the function F, not a redefinition of F. The void f (int i, int j), void f (int i, int j=3), void f (int i=4, int j=5) are all redefined for the virtual function f.
12. If a virtual function parameter has a default value, the formal parameter of a virtual function in a derived class, regardless of the default value, is overwritten by the default value of the base class when you call a virtual function in a derived class with a pointer, that is, the default value of the derived class does not work. This is not the case when you invoke the function with an object from a derived class.
13. When you call a virtual function with a base class pointer to a derived class, you are using the formal parameters of the virtual function in the base class as standard, that is, as long as the form of the invocation conforms to the criteria defined in the base class for the virtual function. For example, the definition of virtual void f (int i=1,int j=2) {} derived class in the base class is redefined as void f (int i, int j=3) {}, at which point the virtual function f in this derived class must have at least one argument when invoking the object of the derived class. But calling the virtual function with a base class pointer to a derived class can invoke the function f in the derived class without any formal parameters, such as Statement p->f (), which invokes the version of the virtual function in the derived class. When you call a virtual function with a base class pointer to a derived class, you are using the formal parameters of the virtual function in the base class as standard, that is, as long as the form of the invocation conforms to the criteria defined in the base class for the virtual function.
14. Destructors can be virtual functions, but constructors cannot.
15. Pure virtual function Declaration form is virtual type function name (parameter list) = 0; Note that the following is equal to 0;
16. If a class has at least one pure virtual function, the class is abstract.
17. If the base class simply declares a virtual function and does not define a virtual function, the virtual function is a pure virtual function. Any derived class must implement its own version of a pure virtual function. If a pure virtual function is not implemented, then the class is also an abstract class.
18. An abstract class cannot have an object, and an abstract class can be used only as a base class for other classes, because one or more functions in an abstract class are not defined, so you cannot declare an object with an abstract class.
19. You can still declare a pointer with an abstract class that points to a derived class object.
20. If a virtual function is not defined in the derived class, the function defined in the base class is used.
21. Virtual functions are inherited in a hierarchical way, for example, C derives from B and the virtual function in B is redefined in C, and D derives from C and does not redefine the virtual function in B, at which point a base class pointer p is declared, and when P points to class D and calls a virtual function in D, Because the virtual function is not redefined in D, he calls the virtual function version in the base class, and then he calls the virtual function in Class C instead of the virtual function in Class B, because Class C is closer to Class D than Class B. Example: Application of virtual function
Class A
{public:
int A;
virtual void F () {cout<< "continue" << "\ n";}
virtual void h (int i=1,int j=2) {cout<< "Jixu" << "\ n";}
~a () {cout<< "Xi A" << "\ n";}
virtual int b; Error, you cannot declare a member variable to be virtual. }; Class B:public A
{Public:int B;
void f (int i) {cout<< "Paif ()" << "\ n";}//overloaded virtual function f.
void f () {cout<< "paiõqë<< \ n";}//redefine virtual function in derived class F
void h () {int b;b=5; cout<< "Paifu" <<b<< "\ n";} Overload the version of the virtual function H. Note that this is not a redefinition of the base class virtual function.
void h (int i,int j=3) {int b; b=j,cout<< "Paixu" <<b<< "\ n";} When a virtual function in a base class has a default parameter, the version of the virtual function in the redefined base class in the derived class must have the same number of formal parameters, either with default values or without. An overload of a virtual function if the number of formal parameters is not as large.
~b () {cout<< "XiB" << "\ n";}};
int main ()
{B m; A *p=&m;
p->b=3/error, the base class pointer to a derived class cannot call a member in a derived class, only members in the base class can be called unless the member is a virtual function.
P->f ()//Call function f in a derived class, output Pailxu
P->f (4) Error, note that this is not a call to the F function with a formal parameter in a derived class, because the F function with one argument is not a virtual function, and the function in the derived class is not invoked when the base class pointer to the derived class is used, unless the function is a virtual function. The F function with one formal parameter is not defined in the base class, so an error occurs.
P->a::f ()//calls the base class's virtual function f, Output Paixu, you can use the scope operator to call the base class's virtual function using a pointer to a derived class
P->h () calls the virtual function version h output paixuH2 in a derived class, and the default value of the virtual function in the derived class does not work here when the virtual function is called with a base class pointer to the derived class. Although a virtual function in a derived class requires a parameter, the argument is not a virtual function H with two arguments to the derived class being invoked, instead of calling the H function with no arguments in the derived class
To invoke a member using a derived class object
M.h (); Call the H function with no arguments in the derived class, and if you want to invoke the H function with two formal parameters in the derived class with the object, you must use an argument value in this example.
M.h (1); Call the H function with two formal parameters in the derived class, output pai˜g†v, the default value of the function is not affected by the default value of the base class virtual function when calling the virtual function in the derived class with the object
M.a::h ();} Call the virtual function h in the base class.
13.1.8 Virtual destructor 1. Why virtual destructors are needed: when memory is allocated dynamically using the new operator, the destructor of the base class should be defined as a virtual destructor, or there will be a problem. For example, Class B is inherited by Class A, then there is the statement a *p= new A;delete p; There is no problem, the destructor of Class A is called to release the resource of Class A. However, if the memory of class B is dynamically assigned to the pointer p, such as p= new B; Delete p; If the destructor of the base class is not a virtual destructor, only the destructor in base class A is called to dispose of the resource without invoking the destructor of the derived class B, when the resource of the derived class B is not freed.
2. The way to solve this problem is to declare the destructor of the base class as a virtual destructor, that is, the virtual keyword is added before the destructor, and when defined as a virtual destructor, when the resource of a derived class is released with Delete, the resource of the derived class is released automatically from the destructor of the derived class, based on the destructor of the base class.
3. As long as the destructor in the base class is a virtual destructor, the destructor in the derived class of the base class is automatically a virtual destructor, although the destructor in the derived class does not have the virtual keyword before the destructor name, but the destructor in the derived class is automatically inherited as a virtual destructor.
4. If you want to use the new operator to allocate memory, it is a good idea to define the destructor as a virtual destructor. Example: Using new to allocate memory, but not defined as a virtual destructor
Class A {public:int A; ~a () {cout<< "XiA" << "\ n";}};
Class B:public A {public:int B; ~b () {cout<< "XiB" << "\ n";}};
Class C:public B{public:int C; ~c () {cout<< "xic" << "\ n";}};
int main ()
{a *p=new A; Delete p;//Output Xia
B m; P=&m This statement is not wrong, but will cause the pointer p to point to a statically allocated memory address, then you cannot use the DELETE statement to release the resource of the pointer p.
Delete p; Error, the pointer p now points to content that is not dynamically allocated memory, but static memory, and delete can only release dynamically allocated memory.
P=new B; Dynamically allocates the memory of the derived class B and assigns the address to the pointer p.
Delete p; Output Xia here does not call the derived class's destructor to free the memory resources of dynamically allocated derived classes.
b *p1=new B; Delete P1; Output Xib XiA
P1=new C; Delete P1; Output Xib Xia Note that there is no resource to release subclass C.
}
Example: Using new to allocate memory, and the base class is defined as the case of a virtual destructor
Class A {Public:int A; virtual ~a () {cout<< "XiA" << "\ n";} };//base class is defined as a virtual destructor
Class B:public A {public:int B; ~b () {cout<< "XiB" << "\ n";}}; Derived class B is automatically inherited as a virtual destructor
Class C:public B {public:int C; ~c () {cout<< "xic" << "\ n";}}; Derived class C is also automatically inherited as a virtual destructor
int main ()
{a p=new A; Delete p; Output Xia
P=new B;
Delete p; Output Xib,xia because the base class defines a virtual destructor, the destructor of the derived class is called here to free the memory resources of the dynamically allocated derived classes and to call the base class's destructor to release the resource of the base class
b *p1= new B; Delete P1; Output Xib,xia
P1=new c;delete p1; //Output Xic,xib,xia here because the destructor of Class B is automatically inherited as a virtual destructor, the release of Subclass C is released here.
Author: Huang Bongyong Shuai