2011-01-28 13 views
21

Estoy escribiendo una aplicación bastante simple en C++ usando g ++ bajo Linux y estoy tratando de lanzar algunas cadenas sin formato como excepciones (sí, lo sé, no es una buena práctica).¿Qué tipo debo capturar si arrojo una cadena literal?

Tengo el siguiente código (simplificado):

int main() 
{ 
    try 
    { 
    throw "not implemented"; 

    } 
    catch(std::string &error) 
    { 
    cerr<<"Error: "<<error<<endl; 
    } 
    catch(char* error) 
    { 
    cerr<<"Error: "<<error<<endl; 
    } 
    catch(...) 
    { 
    cerr<<"Unknown error"<<endl; 
    } 
} 

y me sale Unknow error en la consola. Pero si fijo la cadena literal a std :: string o char * imprime Error: not implemented como se esperaba. Mi pregunta es: ¿cuál es el tipo que debería capturar si no quiero usar moldes estáticos?

+0

Pregunta estúpida: ¿Alguien arroja cosas que no heredan de 'std :: exception' en código real? (Aparte de 'SuicideException', y no, no es burla: p) –

Respuesta

28

Debe capturarlo con char const* en lugar de char*. Ni nada como std::string ni char* lo atrapará.

La captura tiene reglas restringidas con respecto a los tipos que coinciden. La especificación dice (donde "cv" significa "combinación const/volátil" o ninguno de ellos).

Un controlador es un partido para un objeto excepción de tipo E si

  • El controlador es de tipo cv T o cv T & y E y T son del mismo tipo (ignorando el de nivel superior cv-calificadores), o
  • el controlador es de tipo cv T o cv T & y T es una clase base pública inequívoca de e o
  • el controlador es de tipo CV1 T * cv2 y e es un puntero escriba que se puede convertir al tipo de controlador por cualquiera de ambos

    • una conversión puntero estándar (4.10) que no implique conversiones a punteros a privados o protegidos o clases ambiguas
    • una conversión de calificación

Una cadena literal tiene tipo char const[N] , pero lanzar una matriz decaerá la matriz y arrojará un puntero a su primer elemento. Por lo tanto, no puede capturar un literal de cadena arrojado por char*, porque en el momento en que coincida, debe coincidir con char* a char const*, lo que arrojaría una const (una conversión de calificación solo se permite agregar const). La conversión especial de un literal de cadena a char* solo se considera cuando necesita convertir un literal de cadena específicamente.

10

Pruebe agregar const a los tipos que está capturando, const char* (posiblemente const char* const).

+2

' const char * 'funciona. http://ideone.com/6Fzid 'const std :: string &' no. –

+0

¡esto hizo el truco! – Grzenio

+1

O mi favorito personal: 'char const *' –

3

El tipo exacto de una cadena literal es una matriz de caracteres const (const char [15] para su ejemplo, ya que se incluye el terminador NUL).

+0

así que hay alguna posibilidad de atrapar todo esto (para todas las longitudes)? – Grzenio

+3

La matriz se desintegra a 'const char *' cuando se lanza. –

1

El tipo debe ser const char[15] o const char*.

Sin embargo, si bien el idioma no le prohíbe arrojar ningún tipo de valor, no debe generar tipos de datos nativos como excepción.En su lugar, desea generar una instancia std::exception(), o crear su propia clase de excepción.

1

El problema es que estás tratando de atrapar algo que es una const. El siguiente trabajo:

captura (const char * error) { cerr
1

el tipo de una cadena literal es char const *. Hay una conversión (obsoleta) a char * proporcionada por compatibilidad con el código existente (pero aún debe tratarlo como const - cualquier intento de modificación le da a UB).

Como tal, un código como esto debería funcionar:

#include <iostream> 
using namespace std; 

int main() 
{ 
    try 
    { 
    throw "not implemented"; 

    } 
    catch(char const *error) 
    { 
    cerr<<"Error: "<<error<<endl; 
    } 
    return 0; 
} 
1

Mira la sección 2.14.5 de la especificación estándar, que trata a los tipos y clases de cadenas literales en 3 páginas. No hagas lo que comenzó a hacer, simplemente decir:

throw std::exception("not implemented"); 

junto con la adecuada

catch (std::exception& pEx) 

¿Hay algo malo con este enfoque "normal" ...?

+0

¿Hay algún problema con tirar cadenas? –

Cuestiones relacionadas