Acabo de corregir un error muy sutil en nuestro código, causado por el corte de una excepción, y ahora quiero asegurarme de que entiendo exactamente lo que estaba sucediendo.División de excepciones: ¿esto se debe al constructor de copia generado?
Aquí está nuestra clase de excepción base, una clase derivada, y las funciones relevantes:
class Exception
{
public:
// construction
Exception(int code, const char* format="", ...);
virtual ~Exception(void);
<snip - get/set routines and print function>
protected:
private:
int mCode; // thrower sets this
char mMessage[Exception::MessageLen]; // thrower says this FIXME: use String
};
class Derived : public Exception {
public:
Derived (const char* throwerSays) : Exception(1, throwerSays) {};
};
void innercall {
<do stuff>
throw Derived("Bad things happened!");
}
void outercall {
try {
innercall();
}
catch(Exception& e)
{
printf("Exception seen here! %s %d\n", __FILE__, __LINE__);
throw e;
}
}
El error fue, por supuesto que outercall termina por lanzar una excepción, en lugar de un derivado. Mi error fue el resultado de una mayor cantidad de intentos de pila de llamadas para detectar el error Derivado.
Ahora, solo quiero asegurarme de que entiendo: creo que en la línea 'throw e', se está creando un nuevo objeto Exception, utilizando un constructor de copia predeterminado. ¿Eso es lo que realmente está pasando?
Si es así, ¿puedo bloquear los constructores de copia para los objetos que se lanzarán? Realmente preferiría que esto no vuelva a suceder, y nuestro código no tiene ninguna razón para copiar objetos de excepción (que yo sepa).
Por favor, no hay comentarios sobre el hecho de que tenemos nuestra propia jerarquía de excepciones. Es un viejo diseño que estoy trabajando para corregir (estoy progresando bastante. Me he deshecho de la clase de cuerda doméstica y de muchos de los contenedores de fabricación propia).
ACTUALIZACIÓN: Para que quede claro, arreglé el error (cambiando 'throw e' a 'throw') antes de hacer la pregunta. Estaba buscando confirmación de lo que estaba pasando.
Sé que dijiste que no te preocupes por las otras cosas, pero solo dos cosas más: haz que tu clase 'Exception' herede de' std :: exception' y atrapa cosas por 'const &'. – GManNickG
¿Cuál es la ventaja de atrapar como const? Siempre capto por referencia, pero ¿por qué const? (No es que pueda hacer eso con esta clase en este momento de todos modos, pero un día ...) –
@Kohne: La ventaja de const en este entorno es similar a la de cualquier otro entorno: especifica claramente la intención de que no lo haga Tengo la intención de cambiar el estado del objeto y que el compilador debe asegurarse de que no. La idea detrás de esto es que los objetos inmutables son más fáciles de razonar (es decir, depurar, probar, probar el código correcto) ya que ayudan a escribir referencialmente código transparente –