Antes de profundizar en este capítulo, debe tener una buena comprensión de los indicadores y la herencia de la clase. Si no está seguro de lo que significa uno de los siguientes términos, debe consultar las secciones indicadas:
Punteros a la clase base
Una de las principales características de la herencia de clase es que un puntero a una clase derivada es compatible con el tipo con un puntero a su clase base. El polimorfismo es el arte de aprovechar esta característica simple pero poderosa y versátil.
El ejemplo de las clases de rectángulo y triángulo se puede reescribir utilizando punteros que tengan en cuenta esta característica:
// points to base class#include <iostream>using namespace std;class Polygon {protegido:int width, height;public:void set_values (int a, int b){ width=a; height=b; }};class Rectangle: public Polygon {public:int area(){ return width*height; }};class Triangle: public Polygon {public:int area(){ return width*height/2; }};int main () {Rectangle rect;Triangle trgl;Polygon * ppoly1 = ▭Polygon * ppoly2 = &trgl;ppoly1->set_values (4,5);ppoly2->set_values (4,5);cout <<<<< rect.
a
rea() <<<<<<'\n';coste <<<< trgl.area() <<<<'\n';return 0;}
Resultado de la ejecución: 10, 20
La función manual declara dos punteros a Polígono (llamados ppoly1 y ppoly2. Se les asignan las direcciones respectivas de rect y trgl, que son objetos del tipo Rectángulo y Triángulo. Estas asignaciones son válidas, ya que Rectángulo y Triángulo son clases derivadas de Polígono.
La descentralización de ppoly1 y ppoly2 (con * ppoly1 y * ppoly2) es válida y nos permite acceder a los miembros de sus objetos punzantes. Por ejemplo, las dos instrucciones siguientes serían equivalentes en el ejemplo anterior:
ppoly1-> set_values (4,5);rect.set_values (4,5);
Pero como el tipo de ppoly1 y ppoly2 es un puntero a Polígono (y no a Rectángulo o Triángulo), sólo los miembros heredados de Polígono son accesibles, y no los de las clases derivadas Rectángulo y Triángulo. Es por ello que el programa anterior accede a los miembros de la zona de ambos objetos utilizando directamente rect y trgl, en lugar de punteros; los punteros de la clase base no pueden acceder a los miembros de la zona.
Podríamos haber accedido al área de miembros con los punteros sobre el Polígono si el área fuera un miembro del Polígono y no un miembro de sus clases derivadas, pero el problema es que Rectángulo y Triángulo implementan diferentes versiones del área. podría ser implementado en la clase base.
Miembros virtuales
Un miembro virtual es una función de miembro que puede redefinirse en una clase derivada, a la vez que preserva sus propiedades de llamada a través de referencias. La sintaxis para que una función se convierta en virtual es preceder su declaración con la palabra clave virtual:
// miembros virtuales#incluyen <iostream>usando namespace std;class Polígono {protegido:int ancho, alto;público:void set_values (int a, int b){ancho=a; alto=b; }área virtual int (){retorno 0; }};clase Rectángulo: polígono público {público:int área (){ancho de retorno *altura; }};clase Triángulo: polígono público {público {público:
i
nt area (){ return (width * height / 2); }}};int main () {Rectangle rect;Triangle trgl;Polygon poly;Polygon * ppoly1 = ▭Polygon * ppoly2 = &trgl;Polygon * ppoly3 = &poly;ppoly1->set_values (4,5);
p
poly2->valores_de_set (4.5);ppoly3->valores_de_set (4.5);coste <<<<< ppoly1->area() <<<'<<<<<<'ppoly2->area() <<<'\n' \n' \n';return 0;}.
Resultado de la ejecución: 20, 10, 0
En este ejemplo, las tres clases (Polígono, Rectángulo y Triángulo) tienen los mismos miembros: anchura, altura y valores_de_fijación y funciones de área.
(2
) El área de funciones del miembro ha sido declarada virtual en la clase base porque posteriormente se redefine en cada una de las clases derivadas
. Los miembros no virtuales también pueden redefinirse en clases derivadas, pero los miembros no virtuales de las clases derivadas no son accesibles a través de una referencia de clase base: por ejemplo, si se elimina lo virtual de la declaración de zona en el ejemplo anterior, las tres llamadas al área devolverían cero, porque en cualquier caso, se habría llamado la versión de clase base.
Por lo tanto, la palabra clave virtual esencialmente permite que un miembro de una clase derivada con el mismo nombre que la clase base sea llamado apropiadamente desde un puntero, y más precisamente cuando el tipo de puntero es un puntero al puntero. clase base que apunta a un objeto en la clase derivada, como en el ejemplo anterior.
Una clase que declara o hereda una función virtual se llama clase polimórfica.
Nótese que a pesar de la virtualidad de uno de sus miembros, Polygon era una clase regular, de la que incluso un objeto era instanciado (poly), con su propia definición de zona miembro que siempre devuelve 0.
Clases abstractas básicas
Las clases base abstractas son muy similares a la clase Polígono del ejemplo anterior. Estas son clases que sólo pueden ser utilizadas como clases base, y por lo tanto se les permite tener funciones de miembro virtual sin definición (conocidas como funciones puramente virtuales. La sintaxis consiste en sustituir su definición por = 0 (un signo igual y un cero):
Una clase de polígono de base abstracta podría verse así:
// clase abstracta CPolygonclass Polígono {protegido:int ancho, alto;público:void set_values (int a, int b){ ancho=a; alto=b; }área virtual int () =0;};
Tenga en cuenta que este campo no tiene definición; ha sido reemplazado por = 0, lo que lo convierte en una función puramente virtual. Las clases que contienen al menos una función virtual pura se denominan clases base abstractas.
Las clases base abstractas no pueden utilizarse para instanciar objetos. Por lo tanto, esta última versión de la clase base abstracta de Polygon no puede ser usada para declarar objetos como:
Polígono mipolígono; // no funciona si Polígono es una clase base abstracta
Pero una clase de base abstracta no es totalmente inútil. Se puede utilizar para crear punteros y aprovechar todas sus capacidades polimórficas. Por ejemplo, las siguientes sentencias de puntero serían válidas:
Polígono * ppoly1;Polígono * ppoly2;
Y realmente puede ser descodificado cuando usted señala objetos en clases derivadas (no abstractas. Aquí está el ejemplo completo:
// clase base abstracta#incluye <iostream>usando namespace std;class Polígono {protegido:int ancho, alto;público:void set_values (int a, int b){ancho=a; alto=b; }área virtual int (void) =0;};clase Rectángulo: público Polígono {público:int área (void) {retorno (ancho *altura); }};clase Triángulo: público Polígono {págono {público:int area (void){ return (width * height / 2); }}}};int main () {Rectangle rect;Triangle trgl;Polygon * ppoly1 = ▭Polygon * ppoly2 = &trgl;ppoly1->set_values (4,5);ppoly2->set_values (4,5);cost << ppoly1->area() <<< \n';cost <<< ppoly2->area() <<< \n';return 0;}Resultado de la ejecución : 20, 10
En este ejemplo, los objetos de tipos diferentes pero relacionados son referenciados usando un solo tipo de puntero (Polígono *) y la función de miembro apropiada es llamada cada vez, simplemente porque son virtuales. Esto puede ser realmente útil en ciertas circunstancias. Por ejemplo, es incluso posible que un miembro de la clase base Polígono abstracto utilice el puntero especial este para acceder a los miembros virtuales apropiados, incluso si el propio Polígono no tiene una implementación para esta función:
// Un miembro virtual puede ser llamado desde una clase abstracta#include#include <iostream>usando namespace std;class Polygon {protegido:int width, height;public:void set_values (int a, int b){ width=a; height=b; }virtual int area() =0;void printarea(){ cost <<<<<<< `area() < `n'; }};class Rectangle: public Polygonint area (void){ return (width * height); }}}};class Triangle: public Polygon {public:int area (void){ return (width * height / 2); }}}};int main () {Rectangle rect;Triangle trgl;Polygon * ppoly1 = ▭Polígono * ppoly2 = &trgl;ppoly1->set_values (4,5);ppoly2->set_values (4,5);ppoly1->printarea();ppoly2->printarea();return 0;}}.
Los miembros virtuales y las clases abstractas proporcionan características polimórficas C++, muy útiles para proyectos orientados a objetos.
Por supuesto, los ejemplos anteriores son casos de uso muy simples, pero estas características se pueden aplicar a tablas de objetos o a objetos asignados dinámicamente.
Leer tambiénVariables y tipos Aquí hay
un ejemplo que combina algunas de las características de los últimos capítulos, como la memoria dinámica, los inicializadores del fabricante y el polimorfismo
:
// Asignación dinámica y polimorfismo#incluye <iostream>usando namespace std;clase Polígono {protegido:int ancho, alto;público:Polígono (int a, int b) : width(a), height(b) {}virtual int area (void) =0;void printarea(){ cout <<<<<< esta->area() <<'\n'; }};class Rectangle: public Polygon {public:Rectangle(int a,int b) : Polígono(a,b) {}área interior(){ancho de retorno*altura; }};clase Triángulo: público Polígono {público:Triángulo(int a,int b) : Polígono(a,b) {}área de tinta(){ancho de retorno*altura/2; }};int principal () {Polígono * ppoly1 = nuevo Rectángulo (4,5);Polígono * ppoly2 = nuevo Triángulo (4,5);ppoly1->printarea();ppoly2->printarea();borrar ppoly1;eliminar ppoly2;devolver 0;}}.
Observe que la ppoly:
Polígono * ppoly1 = nuevo rectángulo (4,5); Polígono * ppoly2 = nuevo triángulo (4,5);
se declaran como tipo «puntero al polígono», pero se ha declarado que los objetos asignados tienen directamente el tipo de clase derivado (rectángulo y triángulo.
Otros consejos interesantes:
- Las clases en C++ Las clases son un concepto extendido de estructuras de datos: al igual que las estructuras de datos, pueden contener miembros de datos, pero también pueden contener funciones como miembros. Un objeto……
- La Sintaxis Básica de C # C # C # C # es un lenguaje de programación orientado a objetos. En la metodología de programación orientada a objetos, un programa consiste en diferentes objetos que interactúan entre sí a través de acciones. Las acciones que uno……
- Clases en C++ (2) Las clases, esencialmente, definen los nuevos tipos que se utilizarán en el código C++. Y los tipos C++ no sólo interactúan con el código por medio de construcciones y asignaciones. También interactúan…..
- El lenguaje C++ Estos tutoriales explican el lenguaje C++, desde lo básico hasta las últimas características introducidas por C++ 11. Los capítulos tienen una orientación práctica, con ejemplos de programas en todas las secciones para empezar….
- Las clases en C# Al definir una clase, se define un plan para un tipo de datos. Esto no define realmente ningún dato, pero sí define lo que significa la denominación de clase. Es decir, lo que es….