2010-04-03 16 views
10

Teniendo en cuenta este código de ejemplo:C++ Excepciones y herencia de std :: excepción

#include <iostream> 
#include <stdexcept> 

class my_exception_t : std::exception 
{ 
public: 
    explicit my_exception_t() 
    { } 

    virtual const char* what() const throw() 
    { return "Hello, world!"; } 
}; 

int main() 
{ 
    try 
     { throw my_exception_t(); } 
    catch (const std::exception& error) 
     { std::cerr << "Exception: " << error.what() << std::endl; } 
    catch (...) 
     { std::cerr << "Exception: unknown" << std::endl; } 

    return 0; 
} 

me sale el siguiente resultado:

Exception: unknown 

Sin embargo, simplemente haciendo la herencia de my_exception_t de std::exceptionpublic, consigo el siguiente resultado:

Exception: Hello, world! 

Podría alguien pl easy me explica por qué el tipo de herencia importa en este caso? Puntos de bonificación para una referencia en el estándar.

Respuesta

20

Cuando se hereda de forma privada, no se puede convertir a acceder o de otra manera que la clase base fuera de la clase. Has solicitado que algo de la norma:

§11.2/4:
Una clase base se dice que es accesible si un miembro público inventado de la clase base es accesible. Si se puede acceder a una clase base, se puede convertir implícitamente un puntero a una clase derivada en un puntero a esa clase base (4.10, 4.11).

En pocas palabras, para cualquier cosa fuera de la clase es como si nunca hubiera heredado de std::exception, porque es privado. Ergo, no podrá ser atrapado en la cláusula std::exception&, ya que no existe ninguna conversión.

+0

Aceptado para la referencia estándar; ¡Gracias! – fbrereto

9

Podría alguien explicarme por qué el tipo de materia hereditaria en este caso? Puntos de bonificación para una referencia en el estándar.

El tipo de herencia no importa. Solo importa que tenga una conversión accesible disponible para uno de los tipos de captura. Sucede que, dado que no es una herencia pública, no hay una conversión pública accesible.


Explicación:

Se puede ver el mismo comportamiento aquí:

class B 
{ 
}; 

class C1 : B 
{ 
}; 

class C2 : public B 
{ 
}; 

int main(int argc, char** argv) 
{ 
    B& b1 = C1();//Compiling error due to conversion exists but is inaccessible 
    B& b2 = C2();//OK 
    return 0; 
} 

Una excepción lanzada solamente es capturado por un bloque catch si:

  1. La captura el bloque tiene un tipo coincidente, o
  2. El bloque de captura es de un tipo que tiene una conversión accesible
  3. El bloque catch es una captura (...)
+0

'my_exception_t' deriva de' std :: exception' en ambos casos. – fbrereto

+0

@fbrereto: Gracias por la aclaración, expliqué en mi respuesta, por favor vuelva a leer. –