Serie Android C++: Mejores prácticas de C++ 1 Funciones virtuales

¡Acostúmbrate a escribir juntos! Este es el décimo día de mi participación en el "Nuggets Daily New Plan · April Update Challenge", haz clic para ver los detalles del evento .

1. Antecedentes

La base técnica central del polimorfismo de C++ son las funciones virtuales, que nos permiten usar el mismo puntero de clase base para llamar a diferentes implementaciones del mismo método. En el proceso de desarrollo de Android con Java, la tecnología de reescritura de métodos realiza automáticamente el polimorfismo, que puede ser más engorroso desde la perspectiva de C++. Este artículo describe las funciones virtuales de C++ y algunas pautas para el proceso de desarrollo desde la perspectiva de los programadores de Java.

2. ¿Qué es una función virtual?

En Java implementamos dos clases de estructura de herencia:

class Base{
	public void action(){
		System.out.pritln("in Base");
	}
}
class Sub extend Base{
	public void action(){
		System.out.println("in Sub");
	}
}
public static void main(String[] args){
	Base b = new Base();
	b.action();
	b = new Sub();
	b.action();
}
复制代码

Java llamará automáticamente al método correspondiente de la clase real después de que se sobrescriba directamente, pero no en C++.

class Base{
public:
  void action();
}
void Base::action(){
		std::cout>>("in Base");
}
class Sub:public Base{
public:
  void action();
}
void Sub::action(){
		std::cout>>("in Sub");
	}
static void main(){
	Base *b = new Base();
	b->action();
	b = new Sub();
	b->action();
}
复制代码

El resultado impreso es:

in Base
in Base
复制代码

Incluso si b apunta al objeto Sub, el método de Base aún se imprime y no hay vinculación automática.Después de acostumbrarme a escribir Java, inmediatamente me asusto, cómo romperlo. Aquí necesitamos usar nuestra "función virtual" protagonista, agregando la función virtual antes de que la declaración del método se convierta en una función virtual. Agregamos el resultado de la impresión virtual antes de la declaración del método de acción de Base y se convierte en:

in Base
in Sub
复制代码

Actualmente, la llamada se resuelve en tiempo de ejecución solo cuando la función virtual se usa por puntero o referencia, y solo en este caso el tipo dinámico del objeto puede ser diferente del tipo estático.

3. Notas sobre funciones virtuales

  1. Una clase base hace que una función miembro realice un enlace dinámico al preceder la declaración de su función miembro con la palabra clave virtual. Si la clase base declara una función virtual, la función también es implícitamente virtual en la clase derivada. Una clase derivada puede usar la palabra clave virtual antes de las funciones que anula, pero no es obligatorio.
  2. Si queremos usar una clase como clase base, la clase ya debe estar definida y no solo declarada. Debido a que la clase derivada contiene y puede usar los miembros que hereda de la clase base, para usar estos miembros, la clase derivada, por supuesto, necesita saber cuáles son. Una clase no puede derivar de sí misma.
  3. Si la clase base contiene una o más funciones virtuales, podemos usar dynamic_cast para solicitar una conversión de tipo y las comprobaciones de seguridad para esta conversión se realizan en tiempo de ejecución. Del mismo modo, si sabemos que una conversión de base a derivada es segura, podemos usar static_cast para forzar la anulación de las comprobaciones del compilador.
  4. Si no usamos una función, no necesitamos proporcionar una definición para esa función, pero debemos proporcionar una definición para cada función virtual, ya sea que se use o no, porque ni siquiera el compilador puede decir qué función virtual funcionará. ser usado.
  5. El tipo de retorno de la función virtual en la clase derivada debe coincidir con la función de la clase base. La excepción a esta regla es cuando el tipo de devolución virtual de una clase es un puntero o una referencia a la clase misma. Si Impl se deriva de Base, la función virtual de la clase base puede devolver Base*, y la función correspondiente de la clase derivada puede devolver Impl*, dicho tipo de devolución requiere que la conversión de Impl a Base sea accesible.
  6. Podemos designar una función como final, y si la función ya ha sido designada como final, cualquier intento posterior de anular la función generará un error.
  7. Si la función virtual usa argumentos predeterminados, es mejor acumular y definir argumentos predeterminados en la clase derivada.
  8. Si no queremos realizar un enlace dinámico en llamadas a funciones virtuales, podemos usar la aritmética de alcance para forzar la ejecución de una versión específica de la función virtual. Por lo general, solo el código en las funciones miembro (o amigos) necesita usar la aritmética de alcance para eludir el mecanismo de las funciones virtuales. En Java, la subclase puede llamar directamente al método anulado de la superclase super.xxx()En C++, para forzar el uso de una determinada versión de la función virtual, ::se debe usar la clase y el alcance correspondientes de la versión, por ejemplo Base::action(). En Java, si queremos llamar al método anulado de la clase principal de la clase principal, es un poco difícil, pero C++ tiene una ventaja.
  9. Si una función virtual de clase derivada necesita llamar a su versión de clase base, pero no usa el operador de ámbito, la llamada se resolverá en tiempo de ejecución como una llamada a la versión de clase derivada, lo que dará como resultado una recursividad infinita.

4. Resumen

Como una serie de artículos en la dirección de Android C ++, no solo presenta el conocimiento relacionado con C ++, sino que también el principal lenguaje de desarrollo de Android es Java. En el artículo, tratamos de comparar algunas diferencias entre las implementaciones de Java y C ++, como así como algunas ventajas y desventajas. Este artículo presenta las funciones virtuales básicas del polimorfismo de C++ y compara las diferencias con la versión de Java para implementar el polimorfismo.

Supongo que te gusta

Origin juejin.im/post/7085735389079535623
Recomendado
Clasificación