La lógica compleja y el constructor no siempre se combinan bien, y hay fuertes defensores contra el trabajo pesado en un constructor (por razones).
La regla cardinal es que el constructor debe producir un objeto completamente utilizable.
class Vector
{
public:
Vector(): mSize(10), mData(new int[mSize]) {}
private:
size_t mSize;
int mData[];
};
No significa un objeto totalmente inicializado, puede diferir parte de inicialización (piensa perezoso), siempre y cuando el usuario no tiene que pensar en ello.
class Vector
{
public:
Vector(): mSize(0), mData(0) {}
// first call to access element should grab memory
private:
size_t mSize;
int mData[];
};
Si hay trabajo pesado para ser hecho, es posible que decide proceder con un método constructor, que va a hacer el trabajo pesado antes de llamar al constructor. Por ejemplo, imagine recuperar configuraciones de una base de datos y crear un objeto de configuración.
// in the constructor
Setting::Setting()
{
// connect
// retrieve settings
// close connection (wait, you used RAII right ?)
// initialize object
}
// Builder method
Setting Setting::Build()
{
// connect
// retrieve settings
Setting setting;
// initialize object
return setting;
}
Este método de creación es útil si posponer la construcción del objeto produce un beneficio significativo. Por ejemplo, si los objetos toman mucha memoria, posponer la adquisición de memoria después de las tareas que probablemente fallen, puede no ser una mala idea.
Este método de construcción implica Constructor privado y Constructor público (o amigo). Tenga en cuenta que tener un constructor privado impone una serie de restricciones en los usos que se pueden hacer de una clase (no se puede almacenar en contenedores STL, por ejemplo), por lo que es posible que deba fusionarse en otros patrones. Por eso, este método solo debe usarse en circunstancias excepcionales.
Es posible que desee considerar cómo probar tales entidades también, si depende de algo externo (archivo/base de datos), piense en Inyección de dependencia, realmente ayuda con las pruebas unitarias.
http://gotw.ca/gotw/066.htm – DumbCoder
Creo que es una mala idea agregar cosas como 'init()' y 'cleanup()' a las clases. Esto grita por errores. No puede estar seguro si una clase ha sido 'init()' ed. Deberías agregar funciones para verificar esto, pero esto lo hace aún más complejo. – jwueller
@DumbCoder: Lo siento pero no lo entiendo del todo. El artículo que vinculó habla de excepciones, por lo que yo entiendo. – tyrondis