0% encontró este documento útil (0 votos)
5 vistas60 páginas

Herencia Múltiple en C++: Conceptos Clave

El documento discute el tema de la herencia múltiple en C++. Explica conceptos como usar herencia múltiple para combinar interfaces de clases, la memoria asociada con la herencia múltiple, y el casting entre clases derivadas de múltiples clases base.

Cargado por

motorokrjairo
Derechos de autor
© Attribution Non-Commercial (BY-NC)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
5 vistas60 páginas

Herencia Múltiple en C++: Conceptos Clave

El documento discute el tema de la herencia múltiple en C++. Explica conceptos como usar herencia múltiple para combinar interfaces de clases, la memoria asociada con la herencia múltiple, y el casting entre clases derivadas de múltiples clases base.

Cargado por

motorokrjairo
Derechos de autor
© Attribution Non-Commercial (BY-NC)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Programación en C++ (9) : herencia multiple;

patrones

Dr. J.B. Hayet

CENTRO DE INVESTIGACIÓN EN MATEMÁTICAS

Septiembre 2009

,
J.B. Hayet Programación, Septiembre 2009 1 / 60
Outline

1 Herencia multiple

2 Patrones

,
J.B. Hayet Programación, Septiembre 2009 2 / 60
Herencia multiple

Outline

1 Herencia multiple

2 Patrones

,
J.B. Hayet Programación, Septiembre 2009 3 / 60
Herencia multiple

Herencia múltiple
En principio al menos, la herencia múltiple es muy simple : decimos
que una clase C dada herede de A Y de otra clase B, reuniendo las
dos interfaces en una sola.
A B

C D E

,
J.B. Hayet Programación, Septiembre 2009 4 / 60
Herencia multiple

Herencia múltiple : ¿ útil ?

Recordar que esa propiedad que ofrece el lenguaje C++, no le


ofrecen otros lenguajes diseñados para OO, porque lleva a
“problemas” : Java por ejemplo, no lo permite.

,
J.B. Hayet Programación, Septiembre 2009 5 / 60
Herencia multiple

Herencia múltiple : uso tı́pico

Imaginas que te dan dos librerı́as distintas : una que te provee


containers (como listas, vectores. . . ) que almacenan objetos de tipo
Object, la otra que te provee Image. No tienes control sobre esas
clases (las hacen otras personas) : para poder usar Image dentro de
los containers, necesitas crear una nueva clase ObjImage que
hereda de Object y Image.

Remarca importante : con los templates, ese problema se puede


solvar de otra manera, mas simple.

,
J.B. Hayet Programación, Septiembre 2009 6 / 60
Herencia multiple

Herencia múltiple : uso tı́pico


Otro ejemplo tı́pico es cuando dos clases separadas son útiles, y que
también tiene sentido considerar una “unión de las interfaces”. Es el
caso por ejemplo de iostream :
ios

istream ostream

iostream

,
J.B. Hayet Programación, Septiembre 2009 7 / 60
Herencia multiple

Herencia múltiple
Se escribe muy simplemente :
class A {
public :
v o i d methodA ( ) ;
};
class B {
public :
v o i d methodB ( ) ;
};
c l a s s C : p u b l i c A, p u b l i c B {
public :
v o i d methodC ( ) ;
};

,
J.B. Hayet Programación, Septiembre 2009 8 / 60
Herencia multiple

Herencia múltiple

Y se hereda de todos los métodos de las interfaces :


C objC ;
objC . methodA ( ) ;
objC . methodB ( ) ;
objC . methodC ( ) ;
Dos remarcas importantes :
Los controles de acceso vistos precedentemente siguen aquı́.
Como con herencia simple, no hay posibilidad de heredar parte
de una clase (aunque la herencia puede ser private. . . ).

,
J.B. Hayet Programación, Septiembre 2009 9 / 60
Herencia multiple

Herencia múltiple : interfaces puras


Un uso de herencia múltiple que no está contestado : heredar
interfaces puras y combinarlas en una nueva clase. Eso necesita en
C++ el uso de clases abstractas, con métodos virtuales puros
class A {
i n t datoA ;
public :
v i r t u a l v o i d methodA ( ) = 0 ;
};
class B {
i n t datoB ;
public :
v i r t u a l v o i d methodB ( ) = 0 ;
};

,
J.B. Hayet Programación, Septiembre 2009 10 / 60
Herencia multiple

Herencia múltiple : interfaces puras

c l a s s C : p u b l i c A, p u b l i c B {
i n t datoC ;
public :
v o i d methodA ( ) { . . . } ;
v o i d methodB ( ) { . . . } ;
};

,
J.B. Hayet Programación, Septiembre 2009 11 / 60
Herencia multiple

Herencia múltiple : memoria

Sin el virtual :
c o u t << s i z e o f (A) << e n d l ;
c o u t << s i z e o f (B) << e n d l ;
c o u t << s i z e o f (C) << e n d l ;
Me da :

4
4
12

O sea, aparentemente, y lógicamente, se concatenan los datos.

,
J.B. Hayet Programación, Septiembre 2009 12 / 60
Herencia multiple

Herencia múltiple : memoria

Sub-obj. A Sub-obj. B Elementos C

,
J.B. Hayet Programación, Septiembre 2009 13 / 60
Herencia multiple

Herencia múltiple : upcasting


El upcasting es automático y posiciona los apuntadores en el buen
lugar en la clase :
C oc ;
c o u t << &oc << e n d l ;
c o u t << s t a t i c c a s t <A ∗>(&oc ) << e n d l ;
c o u t << s t a t i c c a s t <B ∗>(&oc ) << e n d l ;
Nos da lo correcto :

0xbfffea14
0xbfffea14
0xbfffea18

Pero cuidado que un reinterpret cast no hubiera funcionado !

,
J.B. Hayet Programación, Septiembre 2009 14 / 60
Herencia multiple

Herencia múltiple : upcasting


Y al regresar al apuntador/referencia del tipo original (C *), no hay
problemas, desde cualquier de los dos apuntadores derivados, si
efectivamente estamos en el caso de un apuntador hacia un
sub-objeto de tipo C :
C oc ;
A∗ a p t r = s t a t i c c a s t <A ∗>(&oc ) ;
B∗ b p t r = s t a t i c c a s t <B ∗>(&oc ) ;
c o u t << &oc << e n d l ;
c o u t << s t a t i c c a s t <C ∗>( a p t r ) << e n d l ;
c o u t << s t a t i c c a s t <C ∗>( b p t r ) << e n d l ;
Nos da :
0xbffff03c
0xbffff03c
0xbffff03c
,
J.B. Hayet Programación, Septiembre 2009 15 / 60
Herencia multiple

Herencia múltiple : upcasting

Los offsets están manejados automáticamente entre todos los casts


de apuntadores, pero cuidado al manipularlos mientras se puede:
B bb ;
c o u t << &bb << e n d l ;
c o u t << s t a t i c c a s t <C ∗>(&bb ) << e n d l ;
Me da :

0xbffff038
0xbffff034

pero no lo puedo usar como apuntador a C !

,
J.B. Hayet Programación, Septiembre 2009 16 / 60
Herencia multiple

Herencia múltiple : inicialización

La inicialización en los constructores se hace igual que con


herencia/composición, a través de lista de inicializadores :
C : : C( const C& o b j c ) : A( o b j c ) , B( o b j c ) {
...
}
Notar que el orden de llamada de los constructores en caso default,
o constructores por copia, es el dado en la definición de la herencia
múltiple; los destructores están llamados en el orden reverso.

,
J.B. Hayet Programación, Septiembre 2009 17 / 60
Herencia multiple

Herencia múltiple : clases polimorficas


Asup Bsup

A B

,
J.B. Hayet Programación, Septiembre 2009 18 / 60
Herencia multiple

Herencia múltiple : clases polimorficas

Al heredar de varias clases con funciones virtuales, notar que los


apuntadores hacia las tablas virtuales de cada jerarquı́a están
copiadas también, eso siendo necesario para poder manipular el
objeto como apuntador a cada una de las clases base :
C oc ;
B ∗ b p t r = &oc ; Bsup ∗ b s p t r = b p t r ;
A ∗ a p t r = &oc ; Asup ∗ a s p t r = a p t r ;

,
J.B. Hayet Programación, Septiembre 2009 19 / 60
Herencia multiple

Herencia múltiple : duplicados


Imaginemos ahora que A y B hereden de la misma clase Z. Si C
hereda de los dos, tenemos un problema importante : al imprimir los
tamaños de los objetos, nos da :
C oc ;
c o u t << s i z e o f (A) << e n d l ;
c o u t << s i z e o f (B) << e n d l ;
c o u t << s i z e o f (C) << e n d l ;

8
8
20

O sea, el objeto Z esta presente dos veces en el objeto C !

,
J.B. Hayet Programación, Septiembre 2009 20 / 60
Herencia multiple

Herencia múltiple : duplicados

Sub-obj. A Sub-obj. B Elementos C

Z Z

,
J.B. Hayet Programación, Septiembre 2009 21 / 60
Herencia multiple

Herencia múltiple : duplicados

No es falso, y a priori se podrı́a usar tal cual, pero se rompe el


mecanismo de herencia aquı́ :
No tiene mucho sentido tener que manipular dos instancias del
objeto Z : no habrı́a coherencia.
el upcasting hacia Z no puede funcionar : cual de los dos
objetos se elegirı́a ?
[Link]: error: ’Z’ is an ambiguous base of ’C’
De la misma manera, no se puede invocar a métodos de la base
Z, por la ambigüedad, incluso dentro de los métodos de la clase.

,
J.B. Hayet Programación, Septiembre 2009 22 / 60
Herencia multiple

Herencia múltiple : duplicados


Lo que queremos realmente es que en el caso de que heredamos de
dos clases con base común, esta instancia sea compartida por las
dos clases en el objeto heredando de esas dos clases !
Z

A B

,
J.B. Hayet Programación, Septiembre 2009 23 / 60
Herencia multiple

Herencia múltiple : base virtual

Este mecanismo existe y consiste en hacer de la clase base (Z) una


clase de base virtual :
class A : virtual public Z {
...
};
class B : virtual public Z {
...
};
c l a s s C : p u b l i c A, p u b l i c B {
...
};

,
J.B. Hayet Programación, Septiembre 2009 24 / 60
Herencia multiple

Herencia múltiple : base virtual

El uso de la palabra llave virtual hace que el objeto creado (A o B)


en una jerarquı́a de herencia no instancia él mismo el objeto Z
A∗ a p t r = s t a t i c c a s t <A ∗>(&oc ) ;
B∗ b p t r = s t a t i c c a s t <B ∗>(&oc ) ;
Z ∗ zptr = s t a t i c c a s t <Z ∗>(&oc ) ;
c o u t << &oc << e n d l ;
c o u t << a p t r << e n d l ;
c o u t << b p t r << e n d l ;
c o u t << &oc . datoC << e n d l ;
c o u t << z p t r << e n d l ;

,
J.B. Hayet Programación, Septiembre 2009 25 / 60
Herencia multiple

Herencia múltiple : base virtual

El resultado :

0xbffff02c
0xbffff02c
0xbffff034
0xbffff03c
0xbffff040

Interpretación ? Notar que eso necesita que ambas clases hereden


virtualmente de Z ! Tenemos 8 octetos para A y B : el dato Y un
apuntador hacia el objeto Z común !

,
J.B. Hayet Programación, Septiembre 2009 26 / 60
Herencia multiple

Herencia múltiple : base virtual

La cosa importante en este asunto es que el constructor de Z ya no


lo tienen que manejar A y B, sino la clase mas derivada ! En caso de
creacion de objetos A o B independientes, sı́ se invoca al
constructor de Z pero en el caso de derivación de un objeto cruzado
(con A o algunas de sus derivaciones Y B o una de sus
derivaciones), es a este cruzamiento de hacerlo !

,
J.B. Hayet Programación, Septiembre 2009 27 / 60
Herencia multiple

Herencia múltiple : base virtual


Un problema sigue : los métodos “normales” definidos en las clases
A y B tienen que seguir efectivas a la vez para objetos de estas dos
clases “sólos” o en una clase combinada.
class A : virtual public Z {
i n t datoA ;
public :
A( i n t z , i n t a ) : Z ( z ) { datoA=a ; }
f r i e n d o s t r e a m& o p e r a t o r <<(o s t r e a m& os , const A& a )
r e t u r n o s << s t a t i c c a s t <const Z&>(a )
<< ’ , ’ << a . datoA ;
}
};
Y al imprimir un objeto C ?

,
J.B. Hayet Programación, Septiembre 2009 28 / 60
Herencia multiple

Herencia múltiple : base virtual


El mecanismo de base virtual requiere en varias ocasiones desdoblar
las funciones en dos versiones : la versión para el caso de objeto
instanciado sólo y la versión de una instanciacion de un objeto
“cruzado”.
class A : virtual public Z {
i n t datoA ;
protected :
v o i d l o c a l P r i n t ( o s t r e a m& o s ) const {
o s << ’ , ’<< datoA ; // S o l o l o s d a t o s de A !
}
public :
A( i n t z , i n t a ) : Z ( z ) { datoA=a ; }
f r i e n d o s t r e a m& o p e r a t o r <<(o s t r e a m& os , const A& a )
r e t u r n o s << s t a t i c c a s t <const Z&>(a )
<< ’ , ’ << a . datoA ;
} ,
J.B. Hayet Programación, Septiembre 2009 29 / 60
Herencia multiple

Herencia múltiple : base virtual

Ası́ la clase cruzada llama en su método de impresión : las versiones


localPrint de cada clase madre y la impresión de los datos de C
para evitar duplicar la impresión del objeto de base Z.

,
J.B. Hayet Programación, Septiembre 2009 30 / 60
Herencia multiple

Herencia múltiple : base virtual

La inicialización de los objetos heredados de clases con base virtual


se hace ası́ :
Inicialización de los objetos de bases virtuales, de arriba por
abajo y de izquierda a derecha (según las definiciones de las
clases).
Inicialización de los objetos de base no virtuales.
Inicialización de los elementos de la clase.
Cuerpo del constructor.

,
J.B. Hayet Programación, Septiembre 2009 31 / 60
Herencia multiple

Herencia múltiple : problemas de nombres


Puede haber mas problemas, con los nombres de las clases madres :
class A : virtual public Z {
public :
v o i d someMethod ( ) ;
};
class B : virtual public Z {
public :
v o i d someMethod ( ) ;
};
c l a s s C : p u b l i c A, p u b l i c B {
...
};
C obc ;
o b j c . someMethod ( ) ; // C u a l llamar ?

,
J.B. Hayet Programación, Septiembre 2009 32 / 60
Herencia multiple

Herencia múltiple : problemas de nombres

En este caso, se puede hacer la llamada no ambigua especificando


uno de los dos métodos que llamar, sistemáticamente :
c l a s s C : p u b l i c A, p u b l i c B {
public :
u s i n g A : : someMethod ( ) ; // No hay ambigüedad
};
C obc ;
o b j c . someMethod ( ) ;
pero ya no podemos llamar al de B, sin hacer un cast o escribiendo
un método dedicado dentro de C.

,
J.B. Hayet Programación, Septiembre 2009 33 / 60
Herencia multiple

Herencia múltiple : polimorfismo

Para ambigúedades verticales, el mecanismo de polimorfismo maneja


lo de llamar la función al buen nivel, o sea el más derivado. En
general (el grafo de herencia es mas complicado), se usa el método
dominante, o sea el que tiene el nivel de derivación mas elevado
(que sea heredero directo o indirecto).

,
J.B. Hayet Programación, Septiembre 2009 34 / 60
Herencia multiple

Herencia múltiple : polimorfismo


Z
virtual
void someMethod() ;

A B
void someMethod() ; void someMethod() ;

AMBIGUEDAD

error: no unique final overrider for


’virtual void Z::someMethod()’ in ’C’
,
J.B. Hayet Programación, Septiembre 2009 35 / 60
Herencia multiple

Herencia múltiple : polimorfismo


Z
virtual
void someMethod() ;

Asup
B
void someMethod() ;

void someMethod() ;

A
void someMethod() ;

AMBIGUEDAD

error: no unique final overrider for


’virtual void Z::someMethod()’ in ’C’
,
J.B. Hayet Programación, Septiembre 2009 36 / 60
Herencia multiple

Herencia múltiple : polimorfismo


Z
virtual
void someMethod() ;

Asup

void someMethod() ;

A
void someMethod() ;
OK ! A::someMethod()

,
J.B. Hayet Programación, Septiembre 2009 37 / 60
Herencia multiple

Herencia múltiple : polimorfismo


Eso implica la presencia de una sola jerarquı́a para una(s)
función(es) virtual(es) :
class Z {
public :
v i r t u a l v o i d someMethod ( ) { } ;
};
c l a s s Asup : v i r t u a l p u b l i c Z {
public :
v o i d someMethod ( ) { } ;
};
c l a s s A : p u b l i c Asup {
public :
v o i d someMethod ( ) { } ;
};
c l a s s C : p u b l i c A, v i r t u a l p u b l i c Z {
}; ,
J.B. Hayet Programación, Septiembre 2009 38 / 60
Herencia multiple

dynamic cast y herencia múltiple

El dynamic cast se ocupa de todo para hacer downcast hacia el tipo


derivado :
Z ∗z = new C ; // u p c a s t
C ∗c = d y n a m i c c a s t <C∗>( z ) ; // d o w n c a s t + c h e c k
A ∗a = s t a t i c c a s t <A∗>( c ) ; // Otro u p c a s t
Z ∗ z z= s t a t i c c a s t <Z∗>( c ) ; // Otro u p c a s t

,
J.B. Hayet Programación, Septiembre 2009 39 / 60
Patrones

Outline

1 Herencia multiple

2 Patrones

,
J.B. Hayet Programación, Septiembre 2009 40 / 60
Patrones

Templates : introducción
Hasta ahora, las herramientas que vimos (herencia, composición,
polimorfismo), permiten re-usar código objeto; los patrones (o
templates) permiten hacer una cosa tan interesante : re-usar código
fuente en otros contextos que el para que estaba diseñado :
i n t sum ( i n t a , i n t b ) {
r e t u r n a+b ;
}
f l o a t sum ( f l o a t a , f l o a t b ) {
r e t u r n a+b ;
}
A veces no está muy astuto re-escribir código en funciones sobre
cargadas, ya que el código puede ser exactamente lo mismo !

,
J.B. Hayet Programación, Septiembre 2009 41 / 60
Patrones

Templates : noción de containers

Una justificación muy importante de la introducción de los


templates en el lenguaje C++ es la posibilidad de manejar
containers genéricos. Por container, uno se refiere a una estructura
que guarda una colección de objetos dados, especificando una
manera de introducir/quitar objetos de esta colección. Un arreglo tal
que lo propone C es un container, una pila también.

,
J.B. Hayet Programación, Septiembre 2009 42 / 60
Patrones

Templates : noción de containers

Hasta ahora, los containers que podemos hacer pueden :


estar especializados en un tipo de objetos, por ejemplo enteros,
manipular objetos por apuntadores,
aceptar una jerarquı́a de objetos, y estar expresados en términos
del objeto base; pero no tenemos una sola jerarquı́a en C++.

,
J.B. Hayet Programación, Septiembre 2009 43 / 60
Patrones

Templates : noción de containers

Frecuentemente, lo que se usarán son containers con tipos


apuntadores : por ejemplo, en un sistema de manejo de ventanas.
Esas ventanas pueden estar creadas/destruidas en cualquier
momento, y no se puede predecir cuantas de ellas manejaremos.

En este caso para hacer cosas sobre todas las ventanas, y de todo
modo para guardar en memoria todas las ventanas, se usará un
container de apuntadores hacia ventanas, creadas por new y que
necesitarán estar destruidos con delete.

,
J.B. Hayet Programación, Septiembre 2009 44 / 60
Patrones

Templates : noción de containers


Por ejemplo, una pila de enteros:
class StackInt {
c l a s s Node {
int value ;
Node∗ n e x t ;
v o i d i n i t i a l i z e ( i n t v a l , Node∗ n x t ) ;
};
Node ∗ head ;
void i n i t i a l i z e ( ) ;
void cleanup ( ) ;
public :
StackInt ();
v o i d push ( i n t k ) ;
i n t peek ( ) ;
i n t pop ( ) ;
}; ,
J.B. Hayet Programación, Septiembre 2009 45 / 60
Patrones

Templates : noción de containers

Y si quiero una pila de float ?

Muy probablemente, tendré que escribir una clase MUY SIMILAR,


como StackFloat, para implementarlo. De una manera, tendrá
mucho código duplicado !

,
J.B. Hayet Programación, Septiembre 2009 46 / 60
Patrones

Templates : containers de objetos genéricos

Una opción para salir de este problema es la que adoptan lenguajes


como Java o SmallTalk : todos los objetos del sistema, hasta los
mas básicos, son incluidos en una misma jerarquı́a. Gracias al
polimorfismo, entonces, se puede escribir código para containers de
puros Object.

,
J.B. Hayet Programación, Septiembre 2009 47 / 60
Patrones

Templates : containers de objetos genéricos


Si fuera el caso en C++. . .
c l a s s Stack {
c l a s s Node {
Object ∗ value ;
Node∗ n e x t ;
v o i d i n i t i a l i z e ( O b j e c t ∗ v a l , Node∗ n x t ) ;
};
Node ∗ head ;
void i n i t i a l i z e ( ) ;
void cleanup ( ) ;
public :
Stack ( ) ;
v o i d push ( O b j e c t ∗ k ) ;
Object ∗ peek ( ) ;
O b j e c t ∗ pop ( ) ;
}; ,
J.B. Hayet Programación, Septiembre 2009 48 / 60
Patrones

Templates : containers de objetos genéricos


CONTAINER

Object * Object * Object * Object *

Float Integer Zanahoria Cereza

,
J.B. Hayet Programación, Septiembre 2009 49 / 60
Patrones

Templates : containers de objetos genéricos

Eso es la técnica mas puramente OO, pero no funciona en C++, o


al menos no puede ser tan genérica : el C++ soporta varias
jerarquı́as independientes y no hay tipo base común a todas las
clases, sobre todo.

,
J.B. Hayet Programación, Septiembre 2009 50 / 60
Patrones

Templates : containers de objetos genéricos

La primera solución adoptada fue usar la propiedad de C++ de


permitir herencia múltiple : entonces, hacer clases especiales que
heredan de tus clases originales Y de Object. . . Pero nos lleva todos
los problemas de la herencia múltiple. . .

,
J.B. Hayet Programación, Septiembre 2009 51 / 60
Patrones

Templates : containers de objetos genéricos


Fruta
Object

ObjFruta Fresa Manzana Durazno

ObjFresa ObjManzana ObjDurazno

,
J.B. Hayet Programación, Septiembre 2009 52 / 60
Patrones

Templates
La idea es muy básica : haces un código que manipula objetos de un
tipo genérico, que es un parámetro “como otros” dentro de este
código :
v o i d f o n c (T &someParam ) {
T intermediateValue ;
i n d e r m e d i a t e V a l u e = someParam ∗ 2 ;
...
}
Luego es tarea del compilador de poner un valor a este tipo y de
intentar compilar el código resultante, que eventualmente no tiene
sentido, en función de los usos que intentas hacer de esa
función/esa clase.

,
J.B. Hayet Programación, Septiembre 2009 53 / 60
Patrones

Templates : containers de objetos genéricos


CONTAINER<Float>

Float Float Float Float

CONTAINER<X>
Implementación genérica → cuando se necesita para un tipo en
particular, se compila.

,
J.B. Hayet Programación, Septiembre 2009 54 / 60
Patrones

Templates

El proceso se parece al uso de macros C, en una versión mucho mas


sofisticada. La primera versión de los “templates” por Stroustrup era
de hecho basada en macros, y la versión actual esta mucho mas
avanzada :
Ya no se necesita usar artificialmente jerarquı́as de objetos para
poder usar containers.
Está tal vez mas intuitiva la manera de hacer de los templates :
se programa por ejemplo containers independientemente de
cualquier tipo (después de todo, un container como una pila no
es definido en función de un tipo sino en función de
funcionalidades que ofrece sobre los objetos contenidos).

,
J.B. Hayet Programación, Septiembre 2009 55 / 60
Patrones

Templates : uso
Un ejemplo (1) :
t e m p l a t e <c l a s s T>
class Arreglo {
T ∗ datos ;
unsigned i n t s i z e ;
public :
A r r e g l o ( unsigned i n t s =1) : s i z e ( s ) {
if (! s )
throw 1 ;
d a t o s = new T [ s ] ;
}
˜ Arreglo () {
d e l e t e [ ] datos ;
}

,
J.B. Hayet Programación, Septiembre 2009 56 / 60
Patrones

Templates : uso
Un ejemplo (2) :
T& o p e r a t o r [ ] ( unsigned i n t i n d e x ) {
i f ( i n d e x < 0 && i n d e x >= s i z e ) {
throw 1 ;
}
return datos [ index ] ;
}
};
i n t main ( ) {
A r r e g l o <double> a r r D ;
A r r e g l o <i n t > a r r I ;
}

,
J.B. Hayet Programación, Septiembre 2009 57 / 60
Patrones

Templates : uso
Código objeto correspondiente :
00000076 S __ZN7ArregloIdEC1Ej
000001d4 S __ZN7ArregloIdEC1Ej.eh
00000164 S __ZN7ArregloIdED1Ev
00000254 S __ZN7ArregloIdED1Ev.eh
000000de S __ZN7ArregloIiEC1Ej
00000200 S __ZN7ArregloIiEC1Ej.eh
00000146 S __ZN7ArregloIiED1Ev
0000022c S __ZN7ArregloIiED1Ev.eh

Me generó código objeto “duplicado” a partir de mi patrón, para


enteros y dobles. Hubiera funcionado con cualquier otro tipo.

,
J.B. Hayet Programación, Septiembre 2009 58 / 60
Patrones

Templates : uso

La única cosa que hacer es introducir la definición por :


t e m p l a t e <c l a s s T>

T puede ser cualquiera cosa a priori (clase o tipo elemental).


Por supuesto, puede haber código que no dependa del tipo
“parámetro”.
Si no se usa el patrón (con un tipo T en particular), nada es
compilado en código objeto.

,
J.B. Hayet Programación, Septiembre 2009 59 / 60
Patrones

Templates : uso en funciones no inline

Si no quiero usar funciones inline :


t e m p l a t e <c l a s s T>
A r r e g l o <T> : : A r r e g l o ( unsigned i n t s ) : s i z e ( s ) {
if (! s )
t hro w 1 ;
d a t o s = new T [ s ] ;
}
Se le necesita dar al compilador lo necesario para construir
correctamente los nombres de funciones.

,
J.B. Hayet Programación, Septiembre 2009 60 / 60

También podría gustarte