Std:: исключение подкласс, переменная члена строки

Следующий код работает очень хорошо:

#include <exception>

using namespace std;

class FileException : public exception { // error occurs here
    int _error;
    // string _error; <-- this would cause the error
public:
    FileException(int error);
    // FileException(string error);
    const char* what() const throw();
};

Но как только я изменяю тип _error на строку, возникает следующая ошибка компиляции:

Спецификация исключения для функции переопределения более слабая, чем базовая версия

Ответ 1

Деструктор std::string не является не-броском, что приводит к неявному деструктору FileException. Но деструктор std::exception не-throw, поэтому есть ошибка компилятора.

Вы можете объявить явный деструктор no-throw:

virtual ~FileException() throw() {}

или просто наследуйте от std::runtime_error вместо std::exception, у которого есть конструктор, который принимает вход std::string.

Ответ 2

Упростить с помощью:

// Derive from std::runtime_error rather than std::exception
// std::runtime_error (unlike std::exception) accepts a string as an argument that will
// be used as the error message.
//
// Note: Some versions of MSVC have a non standard std::exception that accepts a string
//       Do not rely on this.
class FileException : public std::runtime_error
{
public:
    // Pass error msg by const reference.
    FileException(std::string const& error)
        // Pass the error to the standard exception
        : std::runtime_error(error)
    {}
    // what() is defined in std::runtime_error to do what is correct
};

Ответ 3

Я одобряю вышеуказанный метод,

но g++, похоже, жалуется, если конструктор по умолчанию отсутствует.

Следующее дополнение делает работу:

using namespace std;

class MyException : public runtime_error {
public:
  /* add the following line: */
  MyException() : runtime_error("MyException") { } // default constructor

  MyException( string const& error ) : runtime_error(error) { }  // ctor w/string
};

Кроме того, список исключений легко создается:

MyException FileNotFound ( "File Not Found" );
MyException ReadOnly     ( "ReadOnly"       );
MyException Unkown       ( "Unknown"        );

...
throw FileNotFound;
...

при перехвате этих исключений, если вам не нужна специфика, поймайте их в общих чертах:

catch( runtime_error re) {  cout << "Runtime Error: " << re.what() << endl;  ... }

Так как все MyExceptions деактируют с runtime_error, это захватывает их всех и вы также не пропустите другие ошибки времени выполнения из системы.

catch( exception e) {  cout << "exception: " << e.what() << endl;  ... }

ловит их все.

В С++ вы также можете бросать и захватывать любые типы (int, boolean, указатели и т.д.). Иногда это проще просто бросить/поймать строку или int внутри функционального блока.

Несколько классов должны только бросать и улавливать стандартные исключения библиотеки кода и их подклассы (и все одинаково), однако, в основном, для согласованности и обслуживания, но также потому, что компиляторы С++ знают, как оптимизировать механизмы исключения и связи для их, и может генерировать интеллектуальные предупреждения и ошибки о них, ослабляя отладки.

"Ошибка:" 0x137F "для ребята IBM, а не" третий парень в проекте в этом году "...