2010-05-18 31 views

Respuesta

23

Puede devolver un puntero de clase abstracta - asumiendo B es una clase concreta derivada de la clase abstracta A:

A * f() { 
    return new B; 
} 

o una referencia:

A & f() { 
    static B b; 
    return b; 
} 

o un puntero inteligente:

std::unique_ptr<A> f() { 
    return std::make_unique<B>(...); 
} 
+0

quiero usar la clase abstracta en sí misma (o su referencia), para usarla como una forma genérica para otras clases que se derivan de esa clase abstracta – cemregoksu

+0

@cemregoksu Ese es el único propósito para tener un resumen clase. Ambas funciones ilustran cómo lo haría con respecto a los valores de retorno de función. –

+0

gracias por su ayuda. Creo que funcionó =) – cemregoksu

3

Las clases abstractas no se pueden crear instancias y, por lo tanto, no se devuelven.

+0

¿Qué hay de la referencia? Sé que no es posible pasar una clase abstracta como parámetro a una función, pero podría pasar la referencia de la clase abstracta. – cemregoksu

+0

Solo si las referencias se refieren realmente a una instancia de una clase secundaria. –

+0

bueno, ¿qué hay de ese escenario? clase A { virtual void f() = 0; }; void fonk (A & a) {} funciona. entonces ¿es posible formar la función para devolver una referencia de la clase otra vez? – cemregoksu

4

No, pero una función podría tener un tipo de devolución de un puntero (o una referencia) a una clase abstracta. Luego devolvería instancias de una clase que se deriva de la clase abstracta.

+0

Se refiere a "tipo de retorno de * una referencia a * una clase abstracta". – avakar

+0

No pude entender lo que quieres decir. puedes dar un pequeño ejemplo? – cemregoksu

+1

@incrediman: entonces él está equivocado. – avakar

16

puede declarar el tipo de devolución para ser una referencia o un puntero a la clase abstracta, de modo que pueda asignarse a referencias o punteros a la clase abstracta y utilizarse en función de su interfaz.

Sin embargo, no puede devolver una instancia real de la clase abstracta real porque, por definición, no puede crear una instancia. Sin embargo, podría devolver instancias de subtipos concretos que sean lo suficientemente buenos porque en el principle of substitution, siempre debería poder usar un subtipo en lugar de un supertipo.

1

La fábrica patrón de diseño es un ejemplo de devolver un puntero a un objeto de clase de resumen:

class Base 
{ ; } 

class One : public Base 
{ ; } 

class Two : public Base 
{ ; } 

Base * Factory(unsigned int number) 
{ 
    Base * p_item(NULL); 
    switch (number) 
    { 
    case 1: 
     p_item = new One; 
     break; 
    case 2: 
     p_item = new Two; 
     break; 
    default: 
     p_item = NULL; 
     break; 
    } 
    return p_item; 
} 

Un objeto de la clase base abstracta real nunca puede ser devuelto desde nunca puede haber una ejemplo de una clase base abstracta. Los punteros y las referencias a un tipo base abstracto se pueden devolver como en el ejemplo anterior.

Los punteros y las referencias a una clase base abstracta devuelta por una función o método hacen referencia en realidad a un descendiente del tipo base abstracto.

-3

Sé que voy poco tarde pero espero que esto ayude a alguien ...

Siendo un novato en C++ de programación, también he estado atrapado durante un tiempo en ese problema. Quería crear un método de fábrica que devuelva una referencia a un objeto abstracto. Mi primera solución con punteros funcionó bien, pero quería mantenerme en una forma más "C++". Aquí está el fragmento de código que escribí para demostrarlo:

#include <iostream> 

using std::cout; 
using std::endl; 

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

class FirstFoo: public Abstract{ 
    void foo() 
    { 
    cout << "Let's go to the foo bar!" << endl; 
    } 
}; 

class SecondFoo: public Abstract{ 
    void foo() 
    { 
    cout << "I prefer the foo beer !" << endl; 
    } 
}; 

Abstract& factoryMethod(){ 
    static int what = 0; 

    if(what++ % 2 == 0) 
    return *(new FirstFoo()); 
    else 
    return *(new SecondFoo()); 
} 

int main(int argc, char* argv[]) 
{ 
    int howMany = 10; 
    int i = 0; 

    while(i++ < howMany) 
    { 
    Abstract& abs = factoryMethod(); 
    abs.foo(); 
    delete &abs; 
    } 
} 

¡Abierto a cualquier crítica!

+3

'factoryMethod' pierde memoria cada vez que lo llamas. El resultado se asigna en el montón, pero nunca se elimina. (La persona que llama no puede eliminarlo porque obtiene una referencia en lugar de un puntero). –

+0

En C++ 11, std :: unique_ptr funciona. – user877329

+0

Estoy de acuerdo con el problema de la pérdida de memoria, pero aprendí cómo importar símbolos específicos de un espacio de nombres usando 'using', ¡hasta ahora solo sabía sobre' using namespace'! Gracias por ese @morandg! – stakx

Cuestiones relacionadas