подкласс std :: exception, строковая переменная-член - PullRequest
11 голосов
/ 23 декабря 2011

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

#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 на строку, возникает следующая ошибка компиляции:

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

Ответы [ 3 ]

23 голосов
/ 23 декабря 2011

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

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

virtual ~FileException() throw() {}

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

6 голосов
/ 23 декабря 2011

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

// 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
};
0 голосов
/ 07 июня 2012

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

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

Следующее дополнение заставляет вещи работать:

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

ловит их всех.

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

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

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

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