You are on page 1of 4

14: Herencia y Composición

Tabla de contenidos
14.1. Sintaxis de la composición
14.2. Sintaxis de la herencia
14.3. Lista de inicializadores de un constructor
14.4. Ocultación de nombres
14.5. Funciones que no heredan automáticamente
14.6. Protected
14.7. Herencia y sobrecarga de operadores
14.8. Herencia múltiple
14.9. Desarrollo incremental
14.10. Upcasting
14.11. Resumen
14.12. Ejercicios
Una de las características más importantes acerca de C++ es la
reutilización de código. Pero para ser revolucionario, necesita ser capaz de
hacer algo más que copiar código y modificarlo.
Este es un enfoque de C y no fue demasiado bien. Como en la
mayoría de los casos en C++, la solución gira alrededor de la clase.
Se reutiliza código creando nuevas clases, pero en vez de crearlas
desde la nada, utilizará clases existentes que alguien ha realizado y
comprobado que funcionan correctamente.
La clave consiste en utilizar estas clases sin modificarlas. En este
capítulo, aprenderá los dos modos de hacerlo. El primero es bastante
directo: simplemente cree objetos de la clase existente dentro de la
nueva clase. A esto se le llama composición porqué la nueva clase
esta compuesta por objetos de clases ya existentes.
La segunda forma es mucho más sutil. Crear la nueva clase como
un tipo de una clase existente. Literalmente se toma la forma de la
clase existente y se añade código, pero sin modificar la clase ya
existente. A este hecho mágico se le llama herencia, y la mayoría del
trabajo es realizado por el compilador. La herencia es uno de los
pilares de la programación orientada a objetos y tiene extensiones
adicionales que serán exploradas en el capítulo 15.
Esto es, resulta que gran parte de la sintaxis y el comportamiento
son similares tanto en la composición como en la herencia (lo cual
tiene sentido; ambas son dos formas de crear nuevos tipos utilizando
tipos ya existentes). En este capítulo, aprenderá acerca de los
mecanismos para la reutilización de código.
14.1. Sintaxis de la composición
Realmente, ha utilizado la composición a lo largo de la creación de
una clase. Ha estado construyendo clases principalmente con tipos
predefinidos (y en ocasiones cadenas). Por esto, resulta fácil usar la
composición con tipos definidos por el usuario.
Considere la siguiente clase:

//: C14:Useful.h

// A class to reuse

#ifndef USEFUL_H

#define USEFUL_H

class X {

int i;

public:

X() { i = 0; }

void set(int ii) { i = ii; }

int read() const { return i; }

int permute() { return i = i * 47; }

};

#endif // USEFUL_H ///:~

Listado 14.1. C14/Useful.h

En esta clase los miembros son privados, y entonces, es


completamente seguro declarar un objeto del tipo X público en la
nueva clase, y por ello, permitir una interfaz directa:

//: C14:Composition.cpp
// Reuse code with composition

#include "Useful.h"

class Y {

int i;

public:

X x; // Embedded object

Y() { i = 0; }

void f(int ii) { i = ii; }

int g() const { return i; }

};

int main() {

Y y;

y.f(47);

y.x.set(37); // Access the embedded object

} ///:~

Listado 14.2. C14/Composition.cpp

Para acceder a las funciones miembro alojadas en el objeto


(referido como subobjeto) simplemente requiere otra selección del
miembro.
Es habitual hacer privado el objeto alojado, y por ello, formar parte
de la capa de implementación (lo que significa que es posible cambiar
la implementación si se desea). La interfaz de funciones de la nueva
clase implica el uso del objeto alojado, pero no necesariamente imita
a la interfaz del objeto.
//: C14:Composition2.cpp

// Private embedded objects

#include "Useful.h"

class Y {

int i;

X x; // Embedded object

public:

Y() { i = 0; }

void f(int ii) { i = ii; x.set(ii); }

int g() const { return i * x.read(); }

void permute() { x.permute(); }

};

int main() {

Y y;

y.f(47);

y.permute();

} ///:~