2017-07-08 1 views
0

J'essaie de créer une classe d'exception personnalisée, la lancer et afficher le message d'erreur, mais je fais quelque chose de mal, provoquant l'exception de ne pas être levée et le message de ne pas être imprimé.Message d'exception personnalisée C++ ne pas afficher

est ici la classe d'exception:

class UnbalancedParenthesesException : public std::exception { 
    int line_number {0}; 
public: 
    UnbalancedParenthesesException(int line_number) : 
    line_number { line_number } 
    {} 

    virtual const char* what() const throw() { 
    std::string exception_message = 
     "Papentheses imbalance at line " + std::to_string(line_number) + "\n"; 

    return exception_message.c_str(); 
    } 
}; 

Je suis en train de try/throw/catch comme suit:

void handle_closed_paren(int line_number) { 
    try { 
    if (definitely_unbalanced()) { 
     throw UnbalancedParenthesesException(line_number); 
    } 
    } catch (const UnbalancedParenthesesException& e) { 
     std::out << e.what() << "\n"; 
} 

Il n'y a rien pertinent à cette erreur dans la console.

Merci d'avance.

+2

'EXCEPTION_MESSAGE retour. c_str(); 'renvoie l'adresse d'une variable de pile locale qui sera détruite sur le retour. –

+0

@RichardCritten: Les réponses vont ci-dessous merci –

+0

Merci, Richard. C'est en effet le problème. – progfan

Répondre

1

Votre programme a un comportement indéfini car vous renvoyez le résultat de c_str() sur un std::string qui est hors de portée. Tout peut arriver. Au-delà, si vous ne voyez pas d'exception, il n'y en a pas eu, probablement parce que le résultat de definitely_unbalanced() est falsey. Parcourez votre programme à l'aide de votre débogueur.

+0

Merci, c'est le problème. Je devrais retourner un 'char *', pas un 'string' local. – progfan

+0

@progfan: Eh bien, non, cela ne semble pas être une solution. Qui crée la chose vers laquelle il pointe? Qui le détruit? Je recommande de garder le 'std :: string' en tant que membre de l'objet d'exception (en le construisant dans le constructeur) alors vous pouvez retourner en toute sécurité son' c_str() '. –

+0

Vous avez raison. Cela devient salissant de cette façon. Je vais construire le 'string' dans le constructeur. – progfan

2

Votre méthode what() crée une variable locale std::string puis retourner un pointeur vers ses données internes, qui seront laissés ballants quand le std::string est hors de portée et est détruit lorsque what() sorties.

Vous devez stocker votre message d'erreur dans un std::string membre de la classe afin qu'il ne soit pas hors de portée prématurément. Heureusement, std::exception a déjà un std::string interne à cet effet. Ainsi, au lieu de formatage du message d'erreur dans what() lui-même, vous devez formater dans votre constructeur dérivé et le transmettre au constructeur de la classe de base, en laissant la base méthode what() il retourne en l'état:

class UnbalancedParenthesesException : public std::exception 
{ 
    int mLineNumber; 
public: 
    UnbalancedParenthesesException(int line_number) : std::exception("Parentheses imbalance at line " + std::to_string(line_number)), mLineNumber(line_number) {} 

    // optional, if the catcher needs access to the value 
    int lineNumber() const { return mLineNumber; } 
}; 
+0

Merci, j'aime cette solution. Je ne savais pas que je pouvais construire comme vous le faites ici. – progfan