Funciones virtuales y funciones virtuales puras en Visual C++ (tome el modo de diseño de apariencia como ejemplo)

Soy Liyuan Breeze, como veterano en la industria de TI durante 25 años, hoy hablaré sobre funciones virtuales y funciones virtuales puras en Visual C++. Todas esta serie de publicaciones utilizan mi propio método de aprendizaje contrastivo. Es decir, cuando no se puede aprender C ++, use JAVA para implementar el mismo código y luego use un método comparativo para aprender C ++.

Mucha gente se mareará al hablar directamente de funciones virtuales y funciones virtuales puras, pero muchas personas que leen esta publicación tienen JAVA u otros fundamentos de programación orientada a objetos, o haré una analogía primero, ¿qué es una función virtual? Y virtual pura Las funciones son en realidad muy simples: los principiantes pueden entender directamente las funciones virtuales y las funciones virtuales puras en C ++ como funciones abstractas en JAVA. ¿Lo entendiste al instante?

También descubrí en la práctica que si primero comprende las clases abstractas y las funciones abstractas de JAVA, le resultará muy sencillo comprender las funciones virtuales y las funciones virtuales puras de C ++. Jaja, este método está bien.

Entonces comprenda lo que dije anteriormente, solo necesitamos distinguir entre funciones virtuales y funciones virtuales puras en C ++ como funciones abstractas en JAVA, y encontrar algunas diferencias entre ellas.

Bueno, la siguiente parte del código es la esencia de este artículo. Compare cuidadosamente los siguientes dos fragmentos de código, uno es C++ y el otro es JAVA. Están logrando lo mismo y el resultado es el mismo, pero la expresión es diferente.

El patrón Facade es un patrón que hace que múltiples subsistemas complejos sean más accesibles al proporcionarles una interfaz consistente.

Tomando como ejemplo un hospital, cuando buscan tratamiento médico, los pacientes deben interactuar con diferentes departamentos funcionales del hospital para completar operaciones como el registro, la consulta ambulatoria y la recolección de medicamentos. Para simplificar el proceso de tratamiento médico, se configura una función de máquina de recepción fácil de usar. Mientras el paciente opere en esta máquina, la máquina puede completar los pasos de tratamiento médico anteriores en nombre del paciente, y el paciente solo necesita para interactuar con la máquina de recepción.

Primero usamos código JAVA para lograr:

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();
}

Luego escribimos el significado anterior nuevamente en el lenguaje C++, más difícil.

#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;
} 

La diferencia entre la clase abstracta de Java y la clase base virtual de C++

Tanto Java como C++ son lenguajes de programación orientados a objetos, que siguen características orientadas a objetos, herencia, encapsulación y polimorfismo. Dado que la clase abstracta de Java es muy similar a la clase base virtual de C++, este artículo hace algunas comparaciones entre los dos conceptos. Del nombre, el concepto estándar:

C++: función virtual, clase base virtual;

java: método abstracto, clase abstracta, interfaz.

En C++, existen funciones virtuales para lograr polimorfismo. En C ++, la palabra clave virtual se utiliza para identificar funciones virtuales, es decir, las funciones miembro ordinarias más las virtuales se convierten en funciones virtuales. No existe el concepto de funciones virtuales en Java. Sus funciones ordinarias son equivalentes a las funciones virtuales de C++. El enlace dinámico es el comportamiento predeterminado de Java. En Java, si un método no desea ser implementado por subclases, use la palabra clave final para convertirlo en una función no virtual. Las funciones abstractas de Java/funciones virtuales puras de C++ son en realidad métodos sin cuerpos de método, es decir, un método solo tiene declaraciones y no tiene definición (implementación). Existen funciones abstractas o funciones virtuales puras para definir interfaces.

 La forma de función virtual pura en C++ es: virtual void print() = 0;

 La forma de función virtual pura en Java es: abstract void print();

La existencia de clases abstractas de Java se debe a que la clase principal incluye no solo la definición específica de las funciones comunes de las subclases, sino también las interfaces de funciones que las subclases deben implementar. Las clases abstractas pueden tener miembros de datos y métodos no abstractos. Es posible que las clases abstractas no tengan métodos abstractos, pero las clases con métodos abstractos deben definirse como clases abstractas y no se pueden crear instancias de clases abstractas. Una clase abstracta en C++ sólo necesita incluir funciones virtuales puras para ser una clase abstracta. Si solo incluye funciones virtuales, no se puede definir como una clase abstracta, porque en realidad no hay ningún concepto abstracto en la clase. Una clase abstracta de Java es una clase declarada con modificación abstracta, mientras que en C++ debe identificarse en forma de virtual void print() = 0;.

Las interfaces Java se definen mediante interfaz. Las variables en la interfaz tienen automáticamente el atributo final estático público, los métodos en la interfaz tienen automáticamente el atributo abstracto público y la interfaz permite la herencia múltiple. Las interfaces no pueden tener variables miembro ordinarias ni pueden tener funciones virtuales no puras.

No existe el concepto de interfaz en C ++. Si todos los métodos son funciones virtuales puras, es decir, todas las clases base virtuales, se puede considerar como el mismo concepto que la interfaz en Java. Estas funciones virtuales puras deben reescribirse mediante subclases, al igual que se deben implementar los métodos en las interfaces de Java.
Tampoco se pueden crear instancias de clases base virtuales. Una función virtual pura no puede tener su propio cuerpo funcional, excepto un destructor virtual puro.

Comparación entre funciones abstractas en JAVA y funciones virtuales en C++

No existe el concepto de función virtual en Java, pero existe el concepto de función abstracta, que está representada por la palabra clave abstracta. Las funciones abstractas en Java deben estar en clases abstractas y las funciones abstractas no pueden tener cuerpos de función. Las clases abstractas no pueden crear instancias , solo sus subclases implementan funciones abstractas. Si una subclase de una clase abstracta sigue siendo una clase abstracta, entonces la subclase no necesita implementar las funciones abstractas de su clase principal.

El concepto de función virtual en C++ está representado por la palabra clave virtual. Cada clase tendrá una tabla de funciones virtuales. La tabla de funciones virtuales primero heredará la tabla de funciones virtuales de la clase principal de la clase principal. Escriba una función virtual de la clase principal clase (independientemente de si la función reescrita es una función virtual o no), qué función virtual llamar se juzga de acuerdo con el objeto real actual (independientemente de si el puntero pertenece a la clase actual o no, puede ser el tipo principal) , a qué tipo de objeto apunta actualmente el puntero, llama a la función virtual definida por la clase en ese tipo. Cada clase tiene solo una tabla de funciones virtuales y todos los objetos comparten esta tabla. El polimorfismo de funciones en C++ se logra mediante funciones virtuales.

En C++, si la función no es una función virtual, la llamada a una determinada función se juzga en función del tipo de puntero actual, no en función del tipo de objeto al que apunta el puntero. En Java, si la función no es una función abstracta, sino una función ordinaria, implementa una función similar a la función virtual en C ++ de forma predeterminada, es decir, llamar a una función se juzga de acuerdo con el tipo de objeto señalado por el puntero actual y No basado en el juicio del tipo de puntero. Justo lo contrario de una función normal en C++. Es decir, las funciones virtuales se implementan automáticamente en JAVA.

Función virtual pura: la característica principal es que no se puede utilizar para declarar objetos, es una clase abstracta y es una herramienta de diseño utilizada para garantizar que la estructura del programa y los datos estructurales del dominio de la aplicación tengan una relación de mapeo directo. Una clase con una función virtual pura se llama clase abstracta. Una clase abstracta puede ser heredada y utilizada por subclases. La implementación de la función virtual pura debe darse en la subclase. Si la subclase no proporciona la implementación de la función virtual pura función, entonces la subclase También es una clase abstracta. ¡Solo cuando la subclase no tiene una función virtual pura, la subclase se puede usar para declarar el objeto! Las clases abstractas también se pueden utilizar para declarar punteros o referencias, o en declaraciones de funciones. Las clases con características de clase abstractas también tienen constructores y destructores, todos los cuales son clases protegidas. Si no se proporciona ninguna implementación de una función virtual pura, no se puede llamar directa o indirectamente desde el constructor o destructor de la clase en la que reside. Las implementaciones de funciones virtuales puras se pueden definir fuera de la declaración de clase.

En C++, el destructor generalmente se declara como una función virtual. Porque las funciones virtuales pueden realizar un enlace dinámico, es decir, qué función llamar se determina según el objeto al que apunta actualmente el puntero, no según el tipo de puntero. Si el destructor no se declara como una función virtual en C++, entonces tiene una subclase que reescribe la función virtual, luego, cuando el puntero de la clase principal apunta a un objeto de la subclase, cuando se llama al destructor, solo se analiza la clase principal. llamado Constructor, pero no se puede llamar al destructor de la subclase, por lo que la situación general es declarar el destructor como una función virtual para lograr un enlace dinámico. Por supuesto, si una clase no contiene funciones virtuales, esto a menudo indica que no está destinada a ser utilizada como clase base. Generalmente es una mala idea declarar virtual un destructor cuando una clase no está destinada a ser una clase base. Por ejemplo: el tipo de cadena estándar no contiene funciones virtuales, si String se hereda como clase base para obtener una subclase, habrá problemas.

En resumen: las clases base polimórficas deberían declarar destructores virtuales. Si una clase tiene funciones virtuales, debe tener un destructor virtual; si no está diseñada para ser una clase base o no está diseñada para polimorfismo, dicha clase no debe declarar un destructor virtual.

Acerca de la interfaz y la clase abstracta: no existe el concepto de interfaz en C ++, y corresponde a una clase virtual pura, es decir, una clase que contiene solo funciones virtuales puras. El concepto de clase abstracta de C ++ es una clase que contiene miembros de funciones virtuales puras. Esto se debe a que C++ proporciona herencia múltiple, mientras que los lenguajes como Java y C# que solo proporcionan herencia única (para evitar la complejidad e ineficiencia de la herencia múltiple) proporcionan el concepto de interfaz para simular la función de herencia múltiple y la interfaz puede heredar. múltiple. Una clase abstracta es una clase abstracta, y una clase que contiene al menos una función virtual pura se llama clase abstracta. Pero si en una clase todos sus miembros son funciones virtuales puras, entonces es diferente de las clases abstractas generales en términos de uso. Al menos las definiciones de interfaz COM dadas por Microsoft son todas clases compuestas únicamente de funciones virtuales puras. Por lo tanto, no es incorrecto llamar a dicha definición de clase una clase virtual pura. La diferencia entre una función virtual pura y una función virtual es que la primera no contiene una definición, mientras que la segunda contiene un cuerpo de función. Entonces, la clase virtual pura no contiene ninguna implementación (incluida la definición de función miembro y la definición de variable miembro. La primera representa el algoritmo y la segunda representa la estructura). Una clase que no contiene ningún algoritmo o estructura se llama clase virtual pura y debería estar bien.

De hecho, no existe el concepto de clase virtual pura en Java, porque no existe el concepto de función virtual pura en Java. La función virtual de Java se llama función abstracta y la clase abstracta se llama clase abstracta. Para decirlo sin rodeos, Java no tiene la palabra clave virtual en absoluto y se usa abstracta en su lugar, por lo que no existe el concepto de puro en Java. Hay una interfaz. Las funciones definidas en la interfaz no pueden tener un cuerpo de función, lo que se denomina interfaz en Java. Entonces, el concepto equivalente a interfaz en C++ es clase virtual pura. C++ usa clases virtuales puras para simular el concepto abstracto de interfaz. Por lo tanto, la "clase virtual pura" mencionada aquí es diferente de la clase abstracta de Java y también es diferente de la de C++. clase abstracta general. . La diferencia entre "clase virtual pura" y clase abstracta general de C++ es como la diferencia entre interfaz y clase abstracta en Java.

Una clase abstracta solo puede usarse como clase base, y la implementación de sus funciones virtuales puras está dada por clases derivadas. Si la clase derivada no redefine la función virtual pura, sino que solo hereda la función virtual pura de la clase base, la clase derivada sigue siendo una clase abstracta. Si la implementación de la función virtual pura de la clase base se da en la clase derivada, la clase derivada ya no es una clase abstracta, sino una clase concreta que puede crear objetos. Las clases abstractas no pueden definir objetos.

Resumir

 Una función virtual en C++ es una función ordinaria en JAVA, una función virtual pura en C++ es una función abstracta en JAVA, una clase abstracta en C++ es una clase abstracta en JAVA y una clase base virtual en C++ es una interfaz en JAVA.


Sobre el autor: Li Yuan Weifeng, nacido en 1981, ingeniero senior, maestro en ingeniería de la Universidad de Zhejiang, supervisor de proyectos de ingeniería de software, ha trabajado como programador, diseñador de software, arquitecto de sistemas, primer programador de Windows, usuario leal de Visual Studio, C/ Usuario de C ++ El autor es un veterano que ha estudiado, trabajado duro y luchado en la industria informática durante 25 años, ha experimentado la era UNIX, la era WIN32 de escritorio, la era de las aplicaciones web, la era de la computación en la nube, el teléfono móvil Android. era, la era del big data, la era de las TIC y la era del aprendizaje profundo de la IA, la era de las máquinas inteligentes, no sé qué era habrá en el futuro, solo recuerdo que este viaje está lleno de dificultades y ganancias. y estoy dispuesto a seguir contigo, lleno de esperanza.

Supongo que te gusta

Origin blog.csdn.net/wang2015cn/article/details/131994075
Recomendado
Clasificación