2012-08-09 15 views
5

El título casi lo dice todo. Básicamente, es legal para hacer esto:C++: ¿puede el vector <Base> contener objetos del tipo Derivado?

class Base { 
    //stuff 
} 

class Derived: public Base { 
    //more stuff 
} 

vector<Base> foo; 
Derived bar; 
foo.push_back(bar); 

Sobre la base de otros mensajes que he visto, lo siguiente es aceptable, pero no quiero utilizar punteros en este caso, porque es más difícil para que sea seguro para subprocesos .

vector<Base*> foo; 
Derived* bar = new Derived; 
foo.push_back(bar); 
+0

¿Por qué es thread- la seguridad de alguna manera relevante aquí? ¿Te refieres a la seguridad de excepción tal vez? Si es así, sí, 'push_back' podría lanzar una excepción, dejando fuera un puntero colgante. Puede usar punteros inteligentes para manejar eso. – DanielKO

+0

@DanielKO Estoy usando un contenedor STL como buffer entre un productor y un hilo de consumidor. No quiero llenar el contenedor con punteros porque, aunque he protegido el contenedor con un mutex, una vez que un hilo tiene un puntero a otros datos, esos datos no están protegidos. – Beezum

+0

Eso en sí mismo no es un problema de seguridad de hilos. Incluso sin punteros uno también puede jugar con los elementos de una manera insegura. Todo lo que tiene que hacer es definir la semántica adecuada para que los contenidos (almacenados como punteros o directamente) no se modifiquen sin los mecanismos de coherencia de concurrencia adecuados. En particular, si teme que un usuario de la clase pueda almacenar un puntero al elemento sin "permiso", ¿qué le hace pensar que no tomará un puntero o una referencia de la misma manera? – DanielKO

Respuesta

13

No, los objetos Derived serán sliced: todos los miembros adicionales serán descartados.

En lugar de punteros sin procesar, use std::vector<std::unique_ptr<Base> >.

+0

@LuchianGrigore "¿el vector contiene objetos del tipo Derivado?" -> No, serán cortados en rodajas, por lo que serán solo objetos 'Base'. No es ilegal, pero tampoco es cierto. – mfontanini

+1

@LuchianGrigore "No, el vector no puede contener objetos de tipo Derivado". Porque una vez que se cortan no son 'Derived' más. – ecatmur

+1

@Heisenbug la 'Base' que termina en el vector es copia construida a partir del objeto' Derived' que se está presionando. Si una construcción de copia genera una fuga, entonces tienes un problema en tu código: D. – mfontanini

4

Es legal pero sufre de corte en rodajas objeto. Básicamente, tendrá un vector de objetos Base. No se perderá ningún tipo de polimorfismo para los objetos derivados ... Es como si acabaras de agregar Base objetos al vector.

En su lugar, puede utilizar punteros inteligentes.

0
vector<Base> foo; 
Derived bar; 
foo.push_back(bar); 

Esto es igual a empujar objeto de base, porque push_back se declara así:

void push_back (const T& x); 

Así, compilador hará la conversión degradación implícita y qué copiar en bloque de memoria vectorial. No, no es posible contener Derived dentro de vector<Base>. Serán Base.

Si se agrega una función virtual para Base entonces anular en Derived, crear Derived objeto, empuje en vector<Base> y luego llamarlo desde nuevo objeto del vector, se verá que Base aplicación se llama

Cuestiones relacionadas