2.2.5a Conversiones estándar con tipos abstractos
§1 Sinopsis
Además de las conversiones estándar realizadas con los tipos básicos ( 2.2.5), existe ocasiones en que el compilador realiza espontáneamente ciertas adaptaciones de tipo para que puedan realizarse determinadas operaciones con objetos abstractos, cuando tales objetos pertenecen a jerarquías de clases.
Nota: las conversiones que se relacionan exigen que la superclase o subclase sean accesibles, y que en casos de herencia múltiple, puedan puedan realizarse sin ambigüedad.
§2 Conversión de referencias
En las jerarquías de clases, las referencias a subclases pueden ser promovidas a referencias a la superclase. El resultado de la conversión es una referencia al subobjeto de la superclase contenido en el objeto de la clase derivada (miembros heredados 4.11.2b). Ejemplo:
class Bas { ... };
class Der : public Bas { ... };
void foo(Bas&);
Der d;
Der& rd = d; // referenica-a-d (objeto de subclase)
En este contexto, aunque foo espera una referencia a la superclase, es legal la invocación:
foo(rd);
El compilador se encarga de realizar una conversión al tipo requerido, de forma que la invocación es transformada en:
foo( (Bas&)rd );
§3 Conversión de punteros a clase
En las jerarquías de clases, los objetos de las clases derivadas pueden utilizarse con punteros a la superclase. En realidad, cuando se manipulan mediante punteros, los objetos de la clase derivada pueden tratarse como si fuesen objetos de la superclase. Ejemplo:
class Bas { ... };
class Der : public Bas { ... };
Bas* bptr; // puntero-a-superclase
Der d; // instancia de sub-clase
En este contexto, aunque bptr es puntero-a-superclase, puede ser asignado con la dirección de un objeto de la subclase. Es legal la asignación:
bptr = &d;
El compilador se encarga de realizar una conversión al tipo requerido, de forma que la asignación es transformada en:
bptr = &( (Bas)d );
Este tipo de conversión Sub-clase* Super-clase* es realizada automáticamente por el compilador en determinadas circunstancias (congruencia estándar de argumentos 4.4.1a).
Nota: cuando se acceden a través de punteros objetos de clases que pertenecen a una jerarquía, es importante tener en cuenta las precauciones indicadas en "Consideraciones sobre punteros en jerarquías de clases" ( 4.11.2b1).
§4 Conversión de punteros a miembro
Con los punteros a miembro ocurre una conversión que, en cierta forma, es inversa de la anterior: los punteros a miembro de una superclase pueden tratarse como si fuesen punteros a objetos de una subclase. Ejemplo:
class Bas {
public: int bi;
};
class Der : public Bas {
public: int di;
};
int Bas::* bpi = &Bas::bi; // puntero-a-miembro de superclase
int Der::* dpi = &Der::di; // puntero-a-miembro de subclase
En este contexto, el puntero puede ser utilizado con objetos de la subclase, en cuyo caso señalará al miembro heredado:
Der d;
Der* dp = &d;
d.*bpi = 2; // Ok. d.bi = 2
dp->*bpi = 3; // Ok. d.bi = 3
d.*dpi = 2; // OK. d.di = 2
dp->*dpi = 3; // Ok. d.di = 3
Bas b;
b.*dpi = 2; // Error!! b NO posee un miembro dpi