Virtual functions and pure virtual functions in Visual C++ (take appearance design mode as an example)

I am Liyuan Breeze. As a veteran in the IT industry for 25 years, today I will talk about virtual functions and pure virtual functions in Visual C++. This series of posts all use my own method of contrastive learning. That is, when C++ cannot be learned, use JAVA to implement the same code, and then use a comparative method to learn C++.

Many people will be dizzy when talking about virtual functions and pure virtual functions directly, but many people who read this post have JAVA or other object-oriented programming foundations, or I will make an analogy first, what is a virtual function? And pure virtual functions are actually very simple. Beginners can directly understand virtual functions and pure virtual functions in C++ as abstract functions in JAVA. Did you understand it instantly?

I also found in practice that if you understand the abstract classes and abstract functions of JAVA first, it will be very simple for you to understand the virtual functions and pure virtual functions of C++. Haha, this method is fine.

Then understand what I said above, we only need to distinguish between virtual functions and pure virtual functions in C++ as abstract functions in JAVA, and find some differences between them.

Well, the following code part is the essence of this article. Please compare the following two pieces of code carefully, one is C++ and the other is JAVA. They are achieving the same thing, and the output is the same, but the expression is different.

The Facade pattern is a pattern that makes multiple complex subsystems more accessible by providing a consistent interface to them.

Taking a hospital as an example, when seeking medical treatment, patients need to interact with different functional departments of the hospital to complete operations such as registration, outpatient consultation, and medicine collection. In order to simplify the medical treatment process, a user-friendly reception machine role is set up. As long as the patient operates on this machine, the machine can complete the above medical treatment steps on behalf of the patient, and the patient only needs to interact with the reception machine.

We first use JAVA code to achieve:

import java.util.*;

interface Patient{
   String getName();
}

interface Disposer{
   void dispose(Patient patient);
}

class Registry implements Disposer{
   //挂号
  public void dispose(Patient patient){
          System.out.println("registering..."+ patient.getName());
  }
}

class Doctor implements Disposer{
   //门诊
  public void dispose(Patient patient){
          System.out.println("diagnosing..."+ patient.getName());
  }
}

class Pharmacy implements Disposer { 
   //取药
  public void dispose(Patient patient){
          System.out.println("giving medicine..."+ patient.getName());
  }
}

class Facade{
  private Patient patient;
  public Facade(Patient patient){this.patient=patient;}
  public void dispose(){
        Registry registry=new Registry();
        Doctor doctor=new Doctor();
        Pharmacy ph=new Pharmacy();

        registry.dispose(patient);
        doctor.dispose(patient);
        ph.dispose(patient);
  }
}

class ConcretePatient implements Patient{
  private String name;
  public ConcretePatient(String name){this.name=name;}
  public String getName(){ return name;}
}

class FacadeTest{
  public static void main(String[] args){
  Patient patient=new ConcretePatient("name");
  Facade f=new Facade(patient);
   f.dispose();
}

Then we write the above meaning again in the more difficult C++ language.

#include <iostream>
#include <string>
using namespace std:

class Patient{
public:
    virtual string getName()=0;
};

class Disposer {
public:
    virtual void dispose(Patient *patient)=0;
};

class Registry:public Disposer{
//挂号
public:
  void dispose(Patient *patient){
       cout<<"registering..."<< patient->getName()<< endl;
    }
};
 
class Doctor:public Disposer{
//门诊
public:
  void dispose(Patient *patient){
       cout <<"diagnosing..."<< patient->getName()<< endl;
  }
};

class Pharmacy: public Disposer{
//取药
public:
  void dispose(Patient *patient){
       cout <<"giving medicine."<< patient->getName()<< endl;
  }
};

class Facade{
private:
  Patient *patient;
public:
  Facade(Patient *patient){ this->patient=patient;}
  void dispose(){
      Registry *registry=new Registry();
      Doctor *doctor=new Doctor();
      Pharmacy *ph=new Pharmacy();

      registry->dispose(patient);
      doctor->dispose(patient);
      ph->dispose(patient);
  }
};

class ConcretePatient:public Patient{
private:
  string name;
public:
  ConcretePatient(string name){this->name=name;}
  string getName(){return name;}
};

int main(){
  Patient *patient=new ConcretePatient("name");
    Facada *f=new Facade(patient);
   f->dispose();
  return 0;
} 

The difference between Java abstract class and C++ virtual base class

Both java and C++ are object-oriented programming languages, following object-oriented features, inheritance, encapsulation, and polymorphism. Since java's abstract class is very similar to C++ virtual base class, this article makes some comparisons between the two concepts. From the name, the standard concept:

C++: virtual function, virtual base class;

java: abstract method, abstract class, interface.

In C++, virtual functions exist to achieve polymorphism. In C++, the virtual keyword is used to identify virtual functions, that is, ordinary member functions plus virtual become virtual functions. There is no concept of virtual functions in Java. Its ordinary functions are equivalent to virtual functions of C++. Dynamic binding is the default behavior of Java. In java, if a method does not want to be implemented by subclasses, use the final keyword to make it a non-virtual function. Java abstract functions/C++ pure virtual functions are actually methods without method bodies, that is, a method has only declarations and no definition (implementation). Abstract functions or pure virtual functions exist to define interfaces.

 The form of pure virtual function in C++ is: virtual void print() = 0;

 The form of pure virtual function in Java is: abstract void print();

The existence of Java abstract classes is because the parent class includes not only the specific definition of the common functions of the subclasses, but also the function interfaces that need to be implemented by the subclasses. Abstract classes can have data members and non-abstract methods. Abstract classes may not have abstract methods, but classes with abstract methods must be defined as abstract classes, and abstract classes cannot be instantiated. An abstract class in C++ only needs to include pure virtual functions to be an abstract class. If it only includes virtual functions, it cannot be defined as an abstract class, because there is actually no abstract concept in the class. A Java abstract class is a class declared with abstract modification, while in C++, it needs to be identified in the form of virtual void print() = 0;.

Java interfaces are defined using interface. The variables in the interface automatically have the public static final attribute, the methods in the interface automatically have the public abstract attribute, and the interface allows multiple inheritance. Interfaces cannot have ordinary member variables, nor can they have non-pure virtual functions.

There is no concept of interface in C++. If all methods are pure virtual functions, that is, all virtual base classes, it can be regarded as the same concept as interface in java. These pure virtual functions must be rewritten by subclasses, just like methods in interfaces in java must be implemented.
Virtual base classes also cannot be instantiated. A pure virtual function cannot have its own function body, except for a pure virtual destructor.

Comparison between abstract functions in JAVA and virtual functions in C++

There is no concept of virtual function in java, but there is the concept of abstract function, which is represented by the abstract keyword. Abstract functions in java must be in abstract classes, and abstract functions cannot have function bodies. Abstract classes cannot be instantiated, only by their Subclasses implement abstract functions. If a subclass of an abstract class is still an abstract class, then the subclass does not need to implement the abstract functions of its parent class.

The concept of virtual function in C++ is represented by the virtual keyword. Each class will have a virtual function table. The virtual function table will first inherit the virtual function table of the parent class from the parent class. Write a virtual function of the parent class (regardless of whether the rewritten function is a virtual function or not), which virtual function to call is judged according to the current actual object (regardless of whether the pointer belongs to the current class or not, it may be the parent type ), which type of object the pointer currently points to, calls the virtual function defined by the class in that type. Each class has only one virtual function table, and all objects share this table. Function polymorphism in C++ is achieved through virtual functions.

In C++, if the function is not a virtual function, calling a certain function is judged based on the current pointer type, not based on the type of the object pointed to by the pointer. In Java, if the function is not an abstract function, but an ordinary function, it implements the function similar to the virtual function in C++ by default, that is to say, calling a function is judged according to the type of the object pointed by the current pointer, and Not based on pointer type judgment. Just the opposite of a normal function in C++. That is, virtual functions are automatically implemented in JAVA.

Pure virtual function: The main feature is that it cannot be used to declare objects, it is an abstract class, and it is a design tool used to ensure that the program structure and the structure data of the application domain have a direct mapping relationship. A class with a pure virtual function is called an abstract class. An abstract class can be inherited and used by subclasses. The implementation of the pure virtual function must be given in the subclass. If the subclass does not provide the implementation of the pure virtual function, then the subclass It is also an abstract class. Only when the subclass does not have a pure virtual function, the subclass can be used to declare the object! Abstract classes can also be used to declare pointers or references, or in function declarations. Classes with abstract class characteristics also have constructors and destructors, all of which are protected classes. If no implementation of a pure virtual function is given, it cannot be called directly or indirectly from the constructor or destructor of the class in which it resides. Implementations of pure virtual functions can be defined outside of the class declaration.

In C++, the destructor is generally declared as a virtual function. Because virtual functions can realize dynamic binding, that is, which function to call is determined according to which object the pointer currently points to, not according to the type of the pointer. If the destructor is not declared as a virtual function in C++, then it has a subclass that rewrites the virtual function, then when the parent class pointer points to a subclass object, when the destructor is called, only the analysis of the parent class is called. Constructor, but the destructor of the subclass cannot be called, so the general situation is to declare the destructor as a virtual function to achieve dynamic binding. Of course, if a class contains no virtual functions, this often indicates that it is not intended to be used as a base class. It is generally a bad idea to declare a destructor virtual when a class is not intended to be a base class. For example: the standard string type does not contain virtual functions, if String is inherited as a base class to obtain a subclass, there will be problems.

In summary: polymorphic base classes should declare virtual destructors. If a class has any virtual functions, it should have a virtual destructor; if it is not designed to be a base class or not designed for polymorphism, such a class should not declare a virtual destructor.

About interface and abstract class: There is no concept of interface in C++, and it corresponds to pure virtual class, that is, a class containing only pure virtual functions. The concept of C++ abstract class is a class containing pure virtual function members. This is because c++ provides multiple inheritance, and languages ​​like java and c# that only provide single inheritance (to avoid the complexity and inefficiency of multiple inheritance) provide the interface concept in order to simulate the multiple inheritance function, and the interface can inherit multiple. Abstract class is an abstract class, and a class that contains at least one pure virtual function is called an abstract class. But if a class, all members are pure virtual functions, then it is different from general abstract classes in terms of usage. At least the COM interface definitions given by Microsoft are all classes composed only of pure virtual functions. Therefore, it is not wrong to call such a class definition a pure virtual class. The difference between a pure virtual function and a virtual function is that the former does not contain a definition, while the latter contains a function body. Then the pure virtual class does not contain any implementation (including member function definition and member variable definition. The former represents the algorithm, and the latter represents the structure). A class that does not contain any algorithms or structures is called a pure virtual class and should be fine.

There is indeed no concept of pure virtual class in java, because there is no concept of pure virtual function in java. The virtual function of java is called abstract function, and the abstract class is called abstract class. To put it bluntly, java does not have the keyword virtual at all, and abstract is used instead, so there is no concept of pure in java. There is an interface. The functions defined in the interface cannot have a function body, which is called an interface in java. Then the concept equivalent to interface in C++ is pure virtual class. C++ uses pure virtual class to simulate the abstract concept of interface, so the "pure virtual class" mentioned here is different from Java's abstract class, and it is also different from C++'s general abstract class. . The difference between "pure virtual class" and C++ general abstract class is like the difference between interface and abstract class in java.

An abstract class can only be used as a base class, and the implementation of its pure virtual functions is given by derived classes. If the derived class does not redefine the pure virtual function, but only inherits the pure virtual function of the base class, the derived class is still an abstract class. If the implementation of the pure virtual function of the base class is given in the derived class, the derived class is no longer an abstract class, but a concrete class that can create objects. Abstract classes cannot define objects.

Summarize

 A virtual function in C++ is an ordinary function in JAVA, a pure virtual function in C++ is an abstract function in JAVA, an abstract class in C++ is an abstract class in JAVA, and a virtual base class in C++ is an interface in JAVA.


About the author: Li Yuan Weifeng, born in 1981, senior engineer, master of engineering from Zhejiang University, software engineering project supervisor, has worked as a programmer, software designer, system architect, early Windows programmer, loyal Visual Studio user, C/C++ user The author is a veteran who has studied, worked hard, and struggled in the computer industry for 25 years. He has experienced the UNIX era, the desktop WIN32 era, the Web application era, the cloud computing era, the mobile phone Android era, the big data era, the ICT era, and AI deep learning Era, the age of intelligent machines, I don't know what era there will be in the future, I just remember that this journey is full of hardships and gains, and I am willing to go on with you, full of hope.

Guess you like

Origin blog.csdn.net/wang2015cn/article/details/131994075