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