2011-06-05 18 views
5

Supongamos que tengo una clase con una función virtual y una clase derivada que implementa la función virtual de una manera diferente. Supongamos que también tengo un vector de la clase base utilizada para almacenar clases derivadas. ¿Cómo podría ejecutar la función virtual de una clase derivada en el vector sin saber de antemano cuál es la clase derivada? Código mínimo que ilustra el problema:C++: Llamar a la función virtual de la clase derivada

#include <iostream> 
#include <vector> 

class Foo { 
public: 
    virtual void do_stuff (void) { 
     std::cout << "Foo\n"; 
    } 
}; 

class Bar: public Foo { 
public: 
    void do_stuff (void) { 
     std::cout << "Bar\n"; 
    } 
}; 

int main (void) { 
    std::vector <Foo> foo_vector; 
    Bar bar; 

    foo_vector.resize (1); 
    foo_vector [0] = bar; 

    bar.do_stuff();   /* prints Bar */ 
    foo_vector [0].do_stuff(); /* prints Foo; should print Bar */ 
    return 0; 
} 
+7

¿Quizás usando 'std :: vector ' (por puntero, o por referencia), para evitar el corte de objetos? De lo contrario, en el momento en que asigna el objeto 'bar' al vector, se corta (se crea un nuevo' Foo' y se almacena en el vector, en lugar de su 'barra'), que probablemente no es lo que quiere. Sin embargo, usar un puntero hará que el código sea más complicado. – rwong

Respuesta

14

No puede. Los objetos en el vector habrán sido en rodajas - cualquier información de instancia de clase derivada habrá sido cortada, por lo que llamar al método sería una idea súper mala.

Si, por otro lado, tiene un vector de punteros a la base, simplemente llame al método virtual y se invocará la versión de la clase derivada.

+2

Gracias. No tenía conocimiento de cortar, y tu sugerencia resolvió el problema. – Adetque

2

La clase a la que llamas no es una clase de Bar, sino una clase de Foo. Lo que está haciendo al foo_vector [0] = bar; es una llamada del operador implícito = que está haciendo todo lo posible para hacer que algo inteligente suceda. El espacio de memoria sigue siendo del tamaño de un Foo, por lo que nunca puede ser un Bar.

0

Al usar funciones virtuales, utiliza punteros a los objetos. De esta forma, se llama a la función exacta durante el tiempo de ejecución ("¿Cómo podría ejecutar la función virtual de una clase derivada en el vector sin saber de antemano cuál es la clase derivada?" Lo que quiere decir aquí probablemente sea "tiempo de ejecución").

El uso de marcar una función como virtual es eso, le pide al compilador que posponga o resuelva el "TIPO" de un objeto llamando a esa función en tiempo de ejecución en lugar de la forma habitual de "tiempo de compilación". Esto se logra mediante el uso de punteros a los objetos. Por lo tanto, para ponerlo en una línea simple "Usar punteros a objetos para hacer uso de funciones virtuales".

Cuestiones relacionadas