C++ es un lenguaje multi-paradigma. Brilla más brillante y es más poderosa donde los paradigmas se mezclan.
class Property
{
public:
Property(const std::string& name) //note: we don't lightly copy strings in C++
: m_name(name) {}
virtual ~Property() {}
private:
std::string m_name;
};
template< typename T >
class TypedProperty : public Property
{
public:
TypedProperty (const std::string& name, const T& data)
: Property(name), m_data(data);
private:
T m_data;
};
typedef std::vector< std::shared_ptr<Property> > property_list_type;
Editar: ¿Por qué utilizar std::shared_ptr<Property>
en lugar de Property*
?
consideran este código:
void f()
{
std::vector<Property*> my_property_list;
for(unsigned int u=0; u<10; ++u)
my_property_list.push_back(new Property(u));
use_property_list(my_property_list);
for(std::vector<Property*>::iterator it=my_property_list.begin();
it!=my_property_list.end(); ++it)
delete *it;
}
Eso for
lazo allí los intentos de limpieza, eliminación de todas las propiedades en el vector, justo antes de que se sale del ámbito y toma todos los punteros con él.
Ahora, si bien esto podría parecerle excelente a un novato, si usted es un desarrollador de C++ con poca experiencia, ese código debería hacer sonar las alarmas tan pronto como lo vea.
El problema es que la llamada al use_property_list()
podría arrojar una excepción. Si es así, la función f()
se dejará inmediatamente. Para una limpieza adecuada, se invocarán los destructores de todos los objetos automáticos creados en f()
. Es decir, my_property_list
se destruirá adecuadamente. El destructor std::vector
limpiará muy bien los datos que contiene.Sin embargo, contiene punteros, y ¿cómo debería saber std::vector
si estos punteros son los últimos que hacen referencia a sus objetos?
Como no lo sabe, no eliminará los objetos, solo destruirá los punteros cuando destruya su contenido, dejándote con objetos en el montón a los que ya no tienes punteros. Esto es lo que se llama una "fuga".
Para evitar eso, debe detectar todas las excepciones, limpiar las propiedades y volver a lanzar la excepción. Pero luego, en diez años a partir de ahora, alguien tiene que agregar una nueva función a la aplicación 10MLoC a la que ha crecido, y, como tiene prisa, agrega código que deja esa función prematuramente cuando se cumple alguna condición. El código se prueba y funciona y no se cuelga; solo el servidor del que forma parte ahora filtra unos pocos bytes por hora, lo que hace que se bloquee debido a que se ha quedado sin memoria una vez a la semana. Encontrar eso hace que muchas horas de multa depuración.
En pocas palabras: nunca administre los recursos manualmente, siempre envuélvalos en objetos de una clase diseñada para manejar exactamente una instancia de dicho recurso. Para objetos dinámicamente asignados, esos identificadores se llaman "puntero inteligente", y el más utilizado es shared_ptr
.
Similar a lo que quiere usando Boost.Variant: http://stackoverflow.com/questions/1358427/function-which-returns-an-unknown-type – AraK
Boost no es una opción. – hasdf
Tus clases 'PropertyXxxx' necesitan heredar de' clase Property'. Es posible que desee editar su publicación. –