Правильный способ наследования от std :: exception - PullRequest
49 голосов
/ 16 ноября 2011

Я только что создал иерархию исключений и хотел передать char* в конструктор одного из моих производных классов с сообщением о том, что не так, но, очевидно, std::exception не имеет конструктора, который позволил бы мне это сделать. Тем не менее, есть ученик класса по имени what(), который предполагает, что некоторая информация может быть передана.
Как я могу (могу ли я?) Передать текст в производный класс std::exception, чтобы передать информацию с моим классом исключений, чтобы я мог сказать где-нибудь в коде:

throw My_Exception("Something bad happened.");

Ответы [ 5 ]

58 голосов
/ 16 ноября 2011

Я использую следующий класс для моих исключений, и он отлично работает:

class Exception: public std::exception
{
public:
    /** Constructor (C strings).
     *  @param message C-style string error message.
     *                 The string contents are copied upon construction.
     *                 Hence, responsibility for deleting the char* lies
     *                 with the caller. 
     */
    explicit Exception(const char* message):
      msg_(message)
      {
      }

    /** Constructor (C++ STL strings).
     *  @param message The error message.
     */
    explicit Exception(const std::string& message):
      msg_(message)
      {}

    /** Destructor.
     * Virtual to allow for subclassing.
     */
    virtual ~Exception() throw (){}

    /** Returns a pointer to the (constant) error description.
     *  @return A pointer to a const char*. The underlying memory
     *          is in posession of the Exception object. Callers must
     *          not attempt to free the memory.
     */
    virtual const char* what() const throw (){
       return msg_.c_str();
    }

protected:
    /** Error message.
     */
    std::string msg_;
};
52 голосов
/ 16 ноября 2011

Если вы хотите использовать строковый конструктор, вы должны наследовать от std :: runtime_error или std :: logic_error , который реализует строковый конструктор и реализует std ::exception :: what метод.

Тогда это просто случай вызова конструктора runtime_error / logic_error из вашего нового унаследованного класса, или, если вы используете c ++ 11, вы можете использовать наследование конструктора.

7 голосов
/ 16 ноября 2011

Как насчет этого:

class My_Exception : public std::exception
{
public:
virtual char const * what() const { return "Something bad happend."; }
};

Или создайте конструктор, принимающий описание, если хотите ...

5 голосов
/ 12 июля 2018

Если ваша цель - создать исключение, чтобы вы не генерировали универсальное исключение ( cpp: S112 ), вы можете просто захотеть открыть исключение, от которого унаследовали ( C ++ 11 ) с объявлением об использовании.

Вот минимальный пример для этого:

#include <exception>
#include <iostream>

struct myException : std::exception
{
    using std::exception::exception;
};

int main(int, char*[])
{
    try
    {
        throw myException{ "Something Happened" };
    }
    catch (myException &e)
    {
        std::cout << e.what() << std::endl;
    }
    return{ 0 };
}

Как указывает Килиан в разделе комментариев, пример зависит от конкретной реализации std :: exception, которая предлагает больше конструкторов, чем указано здесь .

Во избежание этого вы можете использовать любой из удобных классов, предопределенных в заголовке <stdexcept>. Посмотрите эти " Категории исключений " для вдохновения.

5 голосов
/ 16 ноября 2011

Метод what является виртуальным, и смысл в том, что вы должны переопределить его, чтобы вернуть любое сообщение, которое вы хотите вернуть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...