2011-02-16 18 views
7

¿Qué significa cuando hay una referencia a una clase abstracta? Lo encontré en código y no puedo entenderlo.referencia a la clase abstracta

Pensé que no se podía crear una instancia de una clase abstracta. ¿Cómo puedes darle una referencia?

+2

Esta pregunta es demasiado vaga. Publica una muestra de código y explica por qué te confunde. – aschepler

+0

¿Podría eso significar que podría haber alguna de las subclases concretas en el otro extremo? – Piskvor

Respuesta

13

Una referencia a una clase abstracta es como un puntero a una clase abstracta: necesita hacer referencia a un objeto de alguna subclase no abstracta de la clase abstracta. Puede usar una referencia como esa para llamar a métodos virtuales en la clase referenciada utilizando la sintaxis ., de forma similar a un puntero a una interfaz en Java.

6

Una clase abstracta está diseñada para ser derivada de. El principio de sustitución de Liskov establece aproximadamente que cualquier cosa que use las partes abstractas de los tipos derivados de una base abstracta debería funcionar igualmente bien usando polimórficamente la base. Eso significa que se debe usar una referencia o puntero a la base.

+3

+1 para vincularlo al principio de sustitución Liskov. Tales consejos valiosos guían a los novatos a adentrarse en los dominios más profundos del diseño/programación de software, lo que da como resultado colegas más competentes en los cubículos adyacentes :) –

+0

@ Alles: +1 para darse cuenta de la ventaja a largo plazo de entender a Liskov.;-) –

3
class Abstract 
{ 
public: 
    virtual void foo() = 0; 
}; 

class Implementation : public Abstract 
{ 
public: 
    void foo() { std::cout << "Foo!" << std::endl; } 
}; 

void call_foo(Abstract& obj) { obj.foo(); } 

int main() 
{ 
    Abstract *bar = new Implementation(); 

    call_foo(*bar); 

    delete bar; 
} 

bar es una pointer a una clase abstracta. Se puede desreferenciar usando el operador * y pasarlo como reference en call_foo, porque eso es lo que call_foo está pidiendo (Abstract* pediría un puntero, mientras que Abstract& está pidiendo una referencia).

En lo anterior, se hace pasar la referencia a la clase abstracta, y cuando foo() se llama usando la notación . (en lugar de la notación puntero ->), imprime Foo!, porque eso es lo que la hace Implementation.

Espero que esto ayude.

+0

Por supuesto, ni siquiera necesitas crear un puntero aquí. Puede felizmente reemplazar Resumen * barra = nueva Implementación(); con Resumen & barra = Implementación(); o incluso Barra de implementación; – DanDan

+0

En este caso, sí, pero solo estaba mostrando las diferencias/similitudes entre punteros y referencias. :) – James

+0

Muy bien, buen ejemplo, entonces :) – DanDan

2

Las referencias en C++ se comportan (casi) como punteros ocultos. En particular, el mismo comportamiento polimórfico que puede obtener con un puntero, puede lograrlo con una referencia. Es decir, los siguientes son (casi) equivalentes

int *i = &a; 
int &j = a; 

asumiendo que un era un entero definido en algún lugar de las líneas anteriores. Las siguientes ocurrencias de la referencia j, son perfectamente equivalentes a las ocurrencias de (* i). La principal diferencia es que una referencia no le da el dolor de la administración de la memoria, mientras que un puntero sí (es su responsabilidad manejar los nuevos y eliminar). Además, un puntero no tiene que apuntar a algo, mientras que una referencia no puede existir si no se está refiriendo a algo. Aparte de eso, puedes considerar que se comporten de la misma manera.

Por lo tanto, es absolutamente legal tener una referencia a un objeto abstracto. Lo encontrará a menudo en firmas de funciones, donde el comportamiento polimórfico se puede lograr con referencias o punteros. Pero las referencias dan una sintaxis más ligera, al igual que el siguiente fragmento de código muestra

A a; 
A* ptr = &a; 
A& ref = a; 
ref(); 
ptr->operator()(); 
(*ptr)(); 

asumiendo la clase Una sobrecarga operator().

Cuestiones relacionadas