Slicing de exceção - isso é devido ao construtor de cópia gerado?
Acabei de corrigir um bug muito sutil no nosso código, causado pelo corte de uma exceção, e agora quero ter certeza de que entendi exatamente o que estava acontecendo.
Aqui está nossa classe de exceção de base, uma classe derivada e funções 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;
}
}
O bug foi claro que outercall acaba lançando uma exceção, em vez de um derivado. Meu bug resultou de maior nas tentativas de pilha de chamada para pegar a falha derivada.
Agora, só quero ter certeza de que entendi - acredito que na linha 'throw e', um novo objeto Exception está sendo criado, usando um construtor de cópia padrão. É isso que realmente está acontecendo?
Em caso afirmativo, tenho permissão para bloquear construtores de cópia para objetos que serão lançados? Eu realmente prefiro que isso não aconteça novamente, e nosso código não tem motivos para copiar objetos Exception (que eu conheço).
Por favor, não há comentários sobre o fato de termos nossa própria hierarquia de exceções. Isso é um pouco de design antigo que eu estou trabalhando para corrigir (estou fazendo um bom progresso. Eu me livrei da classe de cordas caseira, e muitos dos recipientes feitos em casa.)
ATUALIZAÇÃO: Para ser claro, eu tinha consertado o bug (alterando 'throw e' para 'throw') antes de fazer a pergunta. Eu estava apenas procurando por confirmação do que estava acontecendo.