La herencia múltiple en c ++

Si una clase C ++ puede heredar de otra, entonces la pregunta surge inmediatamente: "¿Puede una clase heredar de dos (o más) clases?" La respuesta es un rotundo en "Sí".

Puede ser valiosa para ver un ejemplo del mundo real de la herencia múltiple de entender por qué esto es una capacidad vale la pena tener. La mayoría de las universidades ofrecen puestos de trabajo a los estudiantes graduados como profesores ayudantes. Estos individuos son todavía estudiantes y tienen todas las propiedades de un estudiante -, pero, además, también gozan de las características de un instructor. Por lo tanto, lógicamente, su árbol de herencia se ve así:

A & lt; span class =TeachingAssistant hereda de ambos Estudiante "/>
LA Asistente de enseñanza hereda de ambos Estudiante y Instructor.

Expresado en C ++, esto aparecería como sigue:

clase Student {public: doble GPA () - bool inscribirse (Curso) paga -bool (dólares dobles) -} - clase Instructor {public: doble grado (Artefacto) -bool enseñar (Curso) -bool GetPaid (dólares dobles) -} TeachingAssistant -class: Estudiante pública, Instructor pública {public: asesor Instructor (Instructor) -Instructor asesor () -} -

La única diferencia entre este ejemplo y ejemplos de herencia simple es la aparición de dos nombres de clases después de la declaración de Asistente de enseñanza.

Teniendo en cuenta las definiciones de clase solo se muestran, todo lo siguiente puede ser dicho:

TeachingAssistant ta - // obtener una calificación como un d studentdouble = ta.gpa () - // grado un documento como un instructorta.grade (documento) - // me puede pasar un ta a una función que espera un partido Studentvoid (Estudiante ) -partido (ta) - // o una función que espera una velada Instructorvoid (Instructor) -soiree (ta) -

Hasta ahora, todo bien. Lo que no me gusta de la herencia múltiple?

Múltiples ambigüedades

Revisando Estudiante y Instructor clases, tanto de estas clases comparten una característica: un número de identificación asignado por la universidad. Pero si intenta agregar esta propiedad de la siguiente manera, se obtiene nada más que quejas de C ++:

clase Student {public: intid () - doble GPA () - bool inscribirse (Curso) paga -bool (dólares dobles) -} - clase Instructor {public: int id () - doble grado (Artefacto) -bool enseñar (Curso) -bool GetPaid (dólares dobles) -} - clase TeachingAssistant: Estudiante pública, Instructor pública {public: asesor Instructor (Instructor) -Instructor asesor () -

};

Este problema se muestra gráficamente, aquí:

Adición de la etiqueta & lt; span class =id () inmueble para tanto Estudiante y
Agregar el id () propiedad a tanto Estudiante y Instructor provoca confusión.

El problema es que ahora, cuando usted dice algo así como

TeachingAssistant ta-cout lt; lt; "Identificación de TA es" lt; lt; ta.id () - // cuales Identificación?

cual Identificación() está destinado - el que Asistente de enseñanza hereda de Estudiante o el que se hereda de Instructor? La ambigüedad puede resolverse mediante la especificación de la ruta de acceso Identificación (conocido como el nombre completo) Me gusta esto:

cout lt; lt; "Identificación del estudiante de TA es" lt; lt; ta.Student :: id () -

Ahora no hay ambigüedad. Al especificar la clase base, se le dice que C ++ id () para recoger.

La resolución de la ambigüedad: Primer intento

Pero ¿y si las dos instancias de id () son no diferente? Supongamos que, al igual que muchas universidades, una universidad particular, asigna un número de identificación único para los estudiantes y los instructores. En ese caso, lo que realmente quiere es la situación que se muestra en la siguiente imagen: Ahora, un Asistente de enseñanza no tiene más que un solo id () propiedad.

La etiqueta & lt; span class =id () propiedad se hereda de una clase base común a ambos
los id () propiedad se hereda de una clase base común a ambos Estudiante y Instructor.

Para tratar de expresar este estado de cosas en C ++, supongamos el siguiente escrito:

clase Académico {public: int id () -} - clase Estudiante: Académico pública {public: doble GPA () - bool inscribirse (Curso) paga -bool (dólares dobles) -} - clase Instructor: Académico pública {public: doble grado (Artefacto) -bool enseñar (Curso) -bool GetPaid (dólares dobles) -} - clase TeachingAssistant: Estudiante pública, Instructor pública {public: asesor Instructor (Instructor) -Instructor asesor () -} -

Por desgracia (y bastante sorprendente), este enfoque no resuelve el problema en absoluto. Una referencia a ta.id () es todavía ambigua. Resulta que este código no crea la imagen- anterior vez, crea la situación que se muestra aquí:

Una sola clase base puede ser heredada en las subclases varias veces.
Una sola clase base puede ser heredada en las subclases varias veces.

Parece que Asistente de enseñanza ahora hereda Académico dos veces - una vez a través de su Estudiante-Ness, y de nuevo a través de su Instructor-ness. Ahora tiene un Estudiante :: Académico Identificación :: () y un Instructor Académico :: Identificación :: ().

La resolución de la ambigüedad

Con el fin de lograr lo que aparece en la tercera figura de este artículo en C ++, debe recurrir a las llamadas algo C ++ herencia virtual. Esta característica aparece en la acción de la siguiente manera:

clase TeachingAssistant: Estudiante pública virtual, Instructor pública virtual {public: asesor Instructor (Instructor) -Instructor asesor () -} -

La utilización de la virtual palabra clave dice C ++ para combinar las clases de bases comunes que Estudiante y Instructor podrían compartir. Lo siguiente ya no genera un error del compilador:

cout lt; lt; "Identificación del estudiante de TA es" lt; lt; ta.id () - // ningún error ahora

Con la herencia virtual, Asistente de enseñanza hereda una y sólo una copia de Académico y la referencia a ta.id () ya no es ambiguo.




» » » » La herencia múltiple en c ++