Использование объекта формата C ++ Boost в качестве члена исключения

Я пытаюсь написать класс исключений, который должен быть вызван при сбое системного вызова. Исключение должно содержать сообщение разработчика и код ошибки, и это what Метод должен отформатировать сообщение разработчика вместе с кодом ошибки. C способ сделать форматирование snprintfно я пытаюсь этого избежать. Я попытался определить члена класса за исключением типа std::stringstream, Тем не менее, это не сработало, так как stringstream имеет конструктор личных копий. В поисках альтернативы я узнал об объекте формата Boost. Я попытался использовать его и получил другую ошибку:

In file included from tun_device.cc:7:0:
system_error.h:9:7: error: looser throw specifier for ‘virtual SystemError::~SystemError()’
class SystemError : public exception
^
In file included from system_error.h:4:0,
from tun_device.cc:7:
/usr/include/c++/4.8/exception:64:13: error:   overriding ‘virtual std::exception::~exception() throw ()’
virtual ~exception() _GLIBCXX_USE_NOEXCEPT;

Чтобы решить эту проблему, нужно определить мой собственный деструктор:

~SystemError() throw() {

}

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

Вот полный класс:

class SystemError : public exception
{
public:
int m_errno;
const char * m_message;

SystemError(int err, const char * message) :
fmt("%1%: %2%") {
fmt % message % errno;
m_errno = err;
this->m_message = message;
}

const char * what() const throw(){
return fmt.str().c_str();
}

~SystemError()  throw() {

}

private:
format fmt;
};

У меня есть несколько вопросов:

  1. Прежде всего — я изобретаю колесо? Уже есть ли рекомендуемый C ++ способ обработки сбойных системных вызовов?

  2. Почему используется format Класс как член исключения заставляет меня переопределить деструктор по умолчанию?

  3. Есть ли какая-нибудь ловушка, о которой я должен знать теперь, когда я добавил свой собственный деструктор?

  4. Есть ли способ достичь того, что я хочу, используя только стандартную библиотеку C ++?

0

Решение

  • Исключение может быть обработано с использованием стандартного класса исключений или созданием ваших собственных классов, производных от класса std :: exception. Наследование будет использоваться, когда вы захотите расширить уже доступную функциональность, доступную с использованием std :: exception. Таким образом, решение полностью зависит от того, как вы хотите разработать свое приложение.

  • boost :: format не заставляет вас переопределять деструктор. Если вы заметили, что вы производите от std :: exception и составляете boost :: format. Деструктор std :: exception объявлен как виртуальный и не имеет броска.

виртуальное ~ исключение () throw ();

Когда вы опускаете деструктор, компилятор неявно предоставляет деструктор, но этот деструктор не имеет природы throw (), следовательно, ошибка компиляции:

format.cpp:5: error: looser throw specifier for âvirtual SystemError::~SystemError()â
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/exception:63: error:   overriding âvirtual std::exception::~exception() throw ()â

Когда вы предоставляете конструктор, но как:

~ SystemError (); // так как базовый класс std :: exception имеет destrutor без броска, потомок также должен следовать тому же самому, и снова в этом случае получена ошибка времени компиляции: format.cpp: 25: error: свободный указатель броска для виртуального SystemError :: ~ SystemError () â
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/exception:63: ошибка: переопределение виртуального std :: исключение: : ~ exception () throw () â

Чтобы устранить ошибку, SystemError должен определить деструктор, подобный этому:

~SystemeError() throw();

Пример кода SSCCE:

  #include <iostream>
#include<boost/format.hpp>

class SystemError : public std::exception
{
public:
int m_errno;
const char * m_message;

SystemError(int err, const char * message) :
fmt("%1%: %2%") {
fmt % message % err;
m_errno = err;
this->m_message = message;
}

const char * what() const throw(){
return fmt.str().c_str();
}

~SystemError()  throw() {

}

//    ~SystemError()  {
//
//    }private:
boost::format fmt;
};int main(){

return 0;
}
  • Добавление деструктора похоже на принятие ответственности за свои действия. Деструктор может быть использован для очистки любой памяти кучи, назначенной в классе. Отсутствие деструктора приведет к тому, что компилятор предоставит неявный деструктор, который может быть причиной проблем в определенных случаях.

    Ошибка компиляции не будет получена, если обсуждаемый класс имеет примитивные типы данных.

3

Другие решения


По вопросам рекламы [email protected]