C++ object-oriented programming: polymorphism, virtual functions, abstract classes, pure virtual functions

Table of Contents of Series Articles

Chapter 1 C++ Inheritance
Chapter 2 C++ Pointers
Chapter 3 C++ Operator Overloading



Preface

Recently, I am preparing for the postgraduate re-examination. I am learning C++ and treat it as study notes.


1. The relationship between objects in the class inheritance hierarchy

1. Call base class functions from derived class objects

  • Base class pointer points to base class object
  • Derived class pointer points to derived class object
  • The base class pointer points to the derived class object.
    The address of the derived class object is assigned to the base class pointer. The C++ compiler allows such "cross assignment" because every derived class object is a base class object. Please note that although the pointer of the base class actually points to the object of the derived class, the member function of the base class is still called (not the member function of the derived class). The function being called depends on the type of handle (such as a pointer or reference) used to call the function, not the type of object the handle points to . It is possible to call object type functions instead of handle type functions. This is crucial to achieve polymorphic behavior.

2. Point the derived class pointer to the base class object

This is not allowed.
Through a derived class pointer, you can call member functions and data members of the derived class for the object it points to (the base class object). However, base class objects do not provide member functions and data members unique to derived classes. This will cause some problems.

3. Call the member function of the derived class through the base class pointer

Using a base class pointer, the compiler only allows calls to member functions of the base class. Therefore, if a base class pointer points to a derived class object and you try to access a member function that is only available in the derived class , a compilation error will occur. The handle can only call member functions of the class type with which it is associated.

It has been confirmed that the C++ compiler does allow access to members owned only in the derived class through a base class pointer pointing to a derived class object. As long as such a base class pointer is explicitly cast to a derived class pointer, this is downward coercion. Conversion (downcasting) technology.
Call a function declared in the base class. Downcasting technology allows a program to perform operations that only a derived class has through a base class pointer pointing to a derived class object. After downward cast, the program can call derived class functions that are not in the base class. Downcasting is potentially dangerous.

2. Virtual function and virtual destructor

When virtual functions are used, the type of the object that calls the member function , not the type of the handle, determines which version of the virtual function is called.

1.virtual function

Let the program dynamically (that is, at execution time) decide which derived class member function should be called based on the type of object pointed to by the base class pointer at any given time. This is polymorphic behavior.
Declaration of virtual functions
To allow polymorphic behavior, member functions must be declared as virtual functions in the base class and overridden in each derived class. From an implementation perspective, overriding a function is no different than redefining a function (the latter is the approach we've been using so far).

2.Declaration of virtual function

A function overridden in a derived class has the same signature and return value type (i.e. prototype) as the base class function it overrides. If the base class function is not declared as virtual, then this function can be redefined. On the contrary, if a base class function is declared as virtual, then this function can be overridden and cause polymorphic behavior. To declare a virtual function, you must precede the prototype of the function in the base class with the keyword virtual. For example,
the virtual void draw() const;
declaration appears in the base class Shape. The above function prototype declares that the draw function is a virtual function with no parameters and no return value. This function is declared as const, and virtual functions do not necessarily have to be declared as const.
Once a function is declared virtual, it will remain virtual-al in all classes from that point down the inheritance hierarchy, even if derived classes override the function without explicitly declaring it as such. virtual.

3. Call virtual functions

  • Calling a virtual function through a base class pointer or reference
    If a program calls a virtual function through a base class pointer to a derived class object or a base class reference to a derived class object, then the program will call a virtual function based on the type of the pointed object rather than the pointer type, dynamically (that is, When executing) select the correct derived class function. Choosing the appropriate calling function at execution time (not compile time) is called dynamic binding or late binding.

  • Calling a virtual function by object name
    When a virtual function is called by referencing a specific object by name and using the dot member selection operator, the function to be called is determined at compile time (called static binding). A virtual function is a function defined (or inherited) by the class to which that particular object belongs. This is not polymorphic behavior. Therefore, dynamic binding using virtual functions can only be done with pointer (and, as we'll see, reference) handles.

4.Virtual destructor

The virtual destructor is to solve the problem that the pointer of the base class points to the derived class object, and uses the pointer of the base class to delete the derived class object.
If the base class destructor is declared virtual, then any derived class destructor is virtual and overrides the base class destructor. The virtual destructor is as follows:
virtual ~class() {}
Now, if you use the delete operator on a base class pointer to explicitly delete an object in the class hierarchy it points to, the system will The object calls the destructor of the corresponding class. When a derived class object is destroyed, the part of the derived class object that belongs to the base class will also be destroyed, so it is important to execute the destructors of the derived class and the base class. The destructor of the base class is executed automatically after the destructor of the derived class is executed.
If a class contains virtual functions, the class must provide a virtual destructor, even if the destructor is not necessarily required by the class. This ensures that when a derived class object is deleted through a base class pointer, the custom derived class destructor (if it exists) will be called.
Constructors cannot be virtual functions. It is a compilation error to declare a constructor as a virtual function.

5.Final member functions and classes

If the virtual function of the base class is declared final in the prototype, the function cannot be overridden in any derived class. This ensures that the final member function definition of the base class is used by all base class objects and all objects of directly or indirectly derived classes of the base class.

3. Abstract classes and pure virtual functions

1.Abstract class

When referring to a class as a type, it is assumed that the program will create objects of this type. However, in some cases it is useful to define a class that the programmer never intends to instantiate any objects. Such a class is called an abstract class. Because usually abstract classes serve as base classes in the inheritance hierarchy of classes, we call them abstract base classes. These classes cannot be used to instantiate objects because abstract classes are incomplete - their derived classes must define the "missing parts" before objects of these classes can be instantiated.
The purpose of constructing an abstract class is to provide a suitable base class for other classes. A class that can be used to instantiate objects is called a concrete class. These classes define or inherit implementations for every member function they declare. An abstract base class is too broad to define a real object, and something more specific is needed before an object can be considered instantiated.

2. Pure virtual function

A class can be made abstract by declaring one or more of its virtual functions as pure virtual functions. A pure virtual function is a function that is "initialized to 0" when declared, as follows:
virtual void draw() const = 0;
"=0" is called a pure specifier.
Pure virtual functions do not provide specific implementations of functions. Each derived concrete class must rewrite the definitions of pure virtual functions of all base classes to provide specific implementations of these functions. The difference between virtual functions and pure virtual functions is that virtual functions have function implementations and provide derived classes with the option of overriding these functions. On the contrary, pure virtual functions do not provide function implementation, and derived classes need to rewrite these functions to make the derived class a concrete class, otherwise the derived class will still be an abstract class. Pure virtual functions are used when it makes no sense for the base class to implement a function, and the programmer wants to implement this function in all specific derived classes.
Abstract classes define a common, common interface for various classes in the class hierarchy. An abstract class contains one or more pure virtual functions that must be overridden in concrete derived classes.
Failure to override pure virtual functions in a derived class makes the derived class abstract as well.
An abstract class contains at least one pure virtual function. Abstract classes can also have data members and specific functions (including constructors and destructors), which comply with the general rules of inheritance when inherited by derived classes.
Although we cannot instantiate objects of abstract base classes, we can use abstract base classes to declare pointers and references that point to concrete class objects derived from abstract classes. Typically, programs use these pointers and references to polymorphically implement derived class objects.


Guess you like

Origin blog.csdn.net/weixin_43821215/article/details/123660780