15.2.4 virtual and other member functions
Function calls in C ++ do not use dynamic binding by default. To enable dynamic binding, two conditions must be met: first, only the member functions specified as virtual functions can be dynamically bound. The member functions are non-virtual functions by default, and non-virtual functions are not dynamically bound; second, you must call the function through a reference or pointer of the base class type.
1. Conversion from a derived class to a base class
Because each derived class object includes the base class part, you can bind the reference of the base class type to the base class part of the derived class object, or point the base class pointer to the derived class object.
Item_base * item1 = new Bulk_item ();
Item_base & item2 = * item1;
Because the base class type pointer or reference can be used to reference a derived type object, when you use a base class type reference or pointer, you do not know the type of the pointer or reference the bound object: the reference or pointer of the base class type can reference objects of the base class type, or can reference objects of the derived type. Regardless of the type of the actual object, the compiler treats it as a base class object. It is safe to treat a derived class object as a base class object because each derived class object has a base class sub-object. In addition, the derived class inherits the operation of the Base class, that is, any operation that can be performed on the base class object can also be used by the derived class object.
The key points of base class type reference and pointer are static type (static type, known reference type or pointer type during compilation) and dynamic type (dynamic type, pointer or reference the type of the bound object, which is known at runtime) may be different.
2. You can determine the virtual function call at runtime.
Item_base * item1 = new Bulk_item ();
Cout <item1-> net_price (2) <endl; // Bulk_item: net_price () called
Binding a reference or pointer of the base class type to a derived class object does not affect the base object, and the object itself does not change. The actual type of the object may be different from the reference type of the object or the static type of the pointer. This is the key to dynamic binding in C ++.
When a virtual function is called by reference or pointer, the compiler will generate code to determine which function to call at runtime. The called function is a function corresponding to the dynamic type.
The static and dynamic types of references and pointers can be different, which is the cornerstone of C ++ to support polymorphism.
When a function defined in the base class is called through a base class reference or pointer, we do not know the exact type of the object that executes the function. The object that executes the function may be of the base class type, it may also be a derived type.
If a non-virtual function is called, the function defined by the base class type is executed no matter what type the actual object is. If you call a virtual function, you can determine which function to call at runtime. The virtual function at runtime references the version of the Type Definition of the object to which the bound or Pointer Points.
On the other hand, the object is non-polymorphism-the object type is known and remains unchanged. The dynamic type of the object is always the same as the static type, which is opposite to the reference or pointer. The running functions (virtual or non-virtual functions) are defined by the object type.
3. During compilation, determine that the non-virtual call www.2cto.com
Cout <item1-> book () <endl; // Item_base: book () called
Even if Bulk_item defines its own book function version, this call will also call the version in the base class.
Non-virtual functions are always determined by the objects, references, or pointer types that call the function during compilation.
4. overwrite the virtual function mechanism
In some cases, you can use the scope operator to override the virtual function mechanism and emphasize the specific version of the virtual function used for function calling.
Cout <item1-> Item_base: net_price (2) <endl; // Item_base: net_price () called
Only the code in the member functions should use the scope operator to overwrite the virtual function mechanism.
When a virtual function of a derived class calls a base class version, the scope operator must be explicitly used. If the function of the derived class ignores this, the function call is determined at runtime and will be a self-called function, resulting in infinite recursion.
5. virtual functions and default real parameters
Like any other function, virtual functions can also have default real parameters. Generally, if the default real parameter value is used in a given call, the value will be determined during compilation. If a call omitting a real parameter with a default value, all values are defined by the type that calls the function, regardless of the dynamic type of the object. When you call a virtual function through a base class reference or pointer, the default real parameter is the value specified in the base class virtual function declaration. If you call a virtual function through a pointer or reference of a derived class, by default, the real parameter is the value declared in the version of the derived class.
Using different default real parameters in the base and derived classes of the same virtual function is almost troublesome. If you use a base class reference or pointer to call a virtual function, but the actual execution is the version defined in the derived class, this may cause a problem. In this case, the default parameter defined for the base class version of the virtual function is passed to the version defined by the derived class, and the derived class version is defined by different default real parameters.
From xufei96's column