Funciones virtuales de C++
Funciones virtuales de C++
En este tutorial, aprenderemos sobre la función virtual de C++ y su uso con la ayuda de ejemplos.
Una función virtual es una función miembro en la clase base que esperamos redefinir en clases derivadas.
Básicamente, se usa una función virtual en la clase base para garantizar que la función sea anulada . Esto se aplica especialmente a los casos en los que un puntero de la clase base apunta a un objeto de una clase derivada.
Por ejemplo, considere el siguiente código:
class Base {
public:
void print() {
// code
}
};
class Derived : public Base {
public:
void print() {
// code
}
};
Más tarde, si creamos un puntero de Base
escribe para apuntar a un objeto de Derived
class y llama al print()
función, llama al print()
función del Base
clase.
En otras palabras, la función miembro de Base
no se anula.
int main() {
Derived derived1;
Base* base1 = &derived1;
// calls function of Base class
base1->print();
return 0;
}
Para evitar esto, declaramos el print()
función del Base
clase como virtual usando el virtual
palabra clave.
class Base {
public:
virtual void print() {
// code
}
};
Las funciones virtuales son una parte integral del polimorfismo en C++. Para obtener más información, consulta nuestro tutorial sobre el polimorfismo de C++.
Ejemplo 1:Función virtual C++
#include <iostream>
using namespace std;
class Base {
public:
virtual void print() {
cout << "Base Function" << endl;
}
};
class Derived : public Base {
public:
void print() {
cout << "Derived Function" << endl;
}
};
int main() {
Derived derived1;
// pointer of Base type that points to derived1
Base* base1 = &derived1;
// calls member function of Derived class
base1->print();
return 0;
}
Salida
Derived Function
Aquí, hemos declarado el print()
función de Base
como virtual
.
Entonces, esta función se anula incluso cuando usamos un puntero de Base
tipo que apunta al Derived
objeto derivado1 .
Identificador de anulación de C++
C++ 11 nos ha dado un nuevo identificador override
eso es muy útil para evitar errores al usar funciones virtuales.
Este identificador especifica las funciones miembro de las clases derivadas que anulan la función miembro de la clase base.
Por ejemplo,
class Base {
public:
virtual void print() {
// code
}
};
class Derived : public Base {
public:
void print() override {
// code
}
};
Si usamos un prototipo de función en Derived
class y definimos esa función fuera de la clase, luego usamos el siguiente código:
class Derived : public Base {
public:
// function prototype
void print() override;
};
// function definition
void Derived::print() {
// code
}
Uso de anulación de C++
Al usar funciones virtuales, es posible cometer errores al declarar las funciones miembro de las clases derivadas.
Usando el override
El identificador solicita al compilador que muestre mensajes de error cuando se cometen estos errores.
De lo contrario, el programa simplemente compilará pero la función virtual no se anulará.
Algunos de estos posibles errores son:
- Funciones con nombres incorrectos: Por ejemplo, si la función virtual en la clase base se llama
print()
, pero accidentalmente nombramos la función superior en la clase derivada comopint()
. - Funciones con diferentes tipos de devolución: Si la función virtual es, digamos, de
void
tipo pero la función en la clase derivada es deint
tipo. - Funciones con diferentes parámetros: Si los parámetros de la función virtual y las funciones de las clases derivadas no coinciden.
- No se declara ninguna función virtual en la clase base.
Uso de funciones virtuales de C++
Supongamos que tenemos una clase base Animal
y clases derivadas Dog
y Cat
.
Supongamos que cada clase tiene un miembro de datos llamado tipo . Supongamos que estas variables se inicializan a través de sus respectivos constructores.
class Animal {
private:
string type;
... .. ...
public:
Animal(): type("Animal") {}
... .. ...
};
class Dog : public Animal {
private:
string type;
... .. ...
public:
Animal(): type("Dog") {}
... .. ...
};
class Cat : public Animal {
private:
string type;
... .. ...
public:
Animal(): type("Cat") {}
... .. ...
};
Ahora, supongamos que nuestro programa requiere que creemos dos public
funciones para cada clase:
getType()
para devolver el valor de tipoprint()
para imprimir el valor de type
Podríamos crear ambas funciones en cada clase por separado y anularlas, lo que sería largo y tedioso.
O podríamos hacer getType()
virtuales en el Animal
clase, luego cree un único print()
separado función que acepta un puntero de Animal
tipo como su argumento. Entonces podemos usar esta única función para anular la función virtual.
class Animal {
... .. ...
public:
... .. ...
virtual string getType {...}
};
... .. ...
... .. ...
void print(Animal* ani) {
cout << "Animal: " << ani->getType() << endl;
}
Esto hará que el código sea más corto , limpiador y menos repetitivo .
Ejemplo 2:Demostración de función virtual de C++
// C++ program to demonstrate the use of virtual function
#include <iostream>
#include <string>
using namespace std;
class Animal {
private:
string type;
public:
// constructor to initialize type
Animal() : type("Animal") {}
// declare virtual function
virtual string getType() {
return type;
}
};
class Dog : public Animal {
private:
string type;
public:
// constructor to initialize type
Dog() : type("Dog") {}
string getType() override {
return type;
}
};
class Cat : public Animal {
private:
string type;
public:
// constructor to initialize type
Cat() : type("Cat") {}
string getType() override {
return type;
}
};
void print(Animal* ani) {
cout << "Animal: " << ani->getType() << endl;
}
int main() {
Animal* animal1 = new Animal();
Animal* dog1 = new Dog();
Animal* cat1 = new Cat();
print(animal1);
print(dog1);
print(cat1);
return 0;
}
Salida
Animal: Animal Animal: Dog Animal: Cat
Aquí, hemos usado la función virtual getType()
y un Animal
puntero ani para evitar repetir el print()
funcionan en todas las clases.
void print(Animal* ani) {
cout << "Animal: " << ani->getType() << endl;
}
En main()
, hemos creado 3 Animal
punteros para crear dinámicamente objetos de Animal
, Dog
y Cat
clases.
// dynamically create objects using Animal pointers
Animal* animal1 = new Animal();
Animal* dog1 = new Dog();
Animal* cat1 = new Cat();
Luego llamamos al print()
función usando estos punteros:
- Cuando
print(animal1)
se llama, el puntero apunta a unAnimal
objeto. Entonces, la función virtual enAnimal
la clase se ejecuta dentro deprint()
. - Cuando
print(dog1)
se llama, el puntero apunta a unDog
objeto. Entonces, la función virtual se anula y la función deDog
se ejecuta dentro deprint()
. - Cuando
print(cat1)
se llama, el puntero apunta a unCat
objeto. Entonces, la función virtual se anula y la función deCat
se ejecuta dentro deprint()
.
Lenguaje C
- Pasar matriz a una función en programación C++
- Clases y objetos de C++
- Función amiga de C++ y Clases amigas
- Plantillas de clase de C++
- Funciones de C++ con ejemplos de programas
- Funciones de Verilog
- C - Funciones
- Clases de almacenamiento en C++
- Sobrecarga de C++ (operador y función)
- Polimorfismo en C++
- Abstracción de datos en C++