2010-04-03 8 views
10

Compte tenu de cet exemple de code:C + Exceptions et héritage de std :: exception

#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; 
} 

Je reçois la sortie suivante:

Exception: unknown 

Pourtant, faisant simplement l'héritage de my_exception_t de std::exceptionpublic, je reçois la sortie suivante:

Exception: Hello, world! 

aisance explique-moi pourquoi le type d'héritage est important dans ce cas? Points bonus pour une référence dans la norme.

Répondre

20

Lorsque vous héritez privé, vous ne pouvez pas convertir ou accéder autrement cette classe de base en dehors de la classe. Depuis que vous avez demandé quelque chose de la norme:

§11.2/4:
Une classe de base est dite accessible si un membre public inventé de la classe de base est accessible. Si une classe de base est accessible, on peut implicitement convertir un pointeur en une classe dérivée en un pointeur vers cette classe de base (4.10, 4.11).

Autrement dit, à quoi que ce soit en dehors de la classe, il est comme jamais hérité de std::exception, parce qu'il est privé. Ergo, il ne pourra pas être attrapé dans la clause std::exception&, puisqu'aucune conversion n'existe.

+0

Accepté pour la référence standard; Merci! – fbrereto

9

Quelqu'un pourrait-il s'il vous plaît me expliquer pourquoi le type de questions d'héritage dans ce cas? Points bonus pour une référence dans la référence.

Le type d'héritage n'a pas d'importance. Il importe seulement que vous ayez une conversion accessible disponible pour l'un des types de captures. Il se trouve juste que puisque ce n'est pas l'héritage public, il n'y a pas de conversion accessible au public.


Explication:

Vous pouvez voir le même comportement ici:

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; 
} 

Une exception levée est uniquement exploitée par un bloc catch si:

  1. Les prises bloc a un type correspondant, ou
  2. Le bloc catch est un type qui a une conversion
  3. accessible Le bloc catch est un catch (...)
+0

'my_exception_t' dérive de' std :: exception' dans les deux cas. – fbrereto

+0

@fbrereto: Merci pour la clarification, j'ai expliqué dans ma réponse s'il vous plaît relire. –