2017-01-19 2 views
10

Я изучаю C++, и я испытываю, когда пытаюсь создать собственное исключение и бросить их в Linux.Создание пользовательских исключений в C++

Я создал небольшой тестовый проект для проверки моей реализации, а ниже мой заголовочный файл класса исключения.

class TestClass : public std::runtime_error 
{ 
public: 
    TestClass(char const* const message) throw(); 
    virtual char const* what() const throw(); 
}; 

Исходный файл для класса исключений является

using namespace std; 

TestClass::TestClass(char const* const message) throw() 
    : std::runtime_error(message) 
{ 

} 

char const * TestClass::what() const throw() 
{ 
    return exception::what(); 
} 

В моем главном приложении, я вызываю функцию, которая бросает мое исключение и ловит его в Try/улове следующим образом:

void runAFunctionAndthrow(); 

/* 
* 
*/ 
int main(int argc, char** argv) { 
    try 
    { 
     cout << "About to call function" << endl; 
     runAFunctionAndthrow(); 
    } 
    catch (TestClass ex) 
    { 
     cout << "Exception Caught: " << ex.what() << endl; 
    } 

    return 0; 
} 

void runAFunctionAndthrow() 
{ 
    cout << "going to run now. oh dear I need to throw an exception" << endl; 

    stringstream logstream; 
    logstream << "This is my exception error. :("; 
    throw TestClass(logstream.str().c_str()); 
} 

Когда я бегу, я ожидал получить следующий вывод:

About to call function

Going to run now. oh dear I need to throw an exception

Exception Caught: This is my exception error. :(

Вместо того, что я получаю

About to call function

going to run now. oh dear I need to throw an exception

Exception Caught: std::exception

Обратите внимание на последней строке говорится станд :: исключение вместо моего фактического сообщения исключений «Это моя ошибка исключение».

Почему это, он работает нормально в Windows, но в Linux он это делает.

Из того, что я видел на разных постах, то, что я сделал, является правильным, так что мне не хватает.

+0

В 'what()' вы, вероятно, имели в виду 'return runtime_error :: what();' - что могло бы полностью исключить повторную реализацию (поведение базового класса здесь уже хорошо для вас). –

ответ

17

Ваш what() возвращается:

return exception::what(); 

Возвращаемое значение std::exception::what() является specified as follows:

Pointer to a null-terminated string with explanatory information.

Вот так. Ничего больше, больше ничего. Текст, который вы показываете, безусловно, квалифицируется как «пояснительная информация». И это единственное требование для возвращаемого значения what() (за исключением одного другого, который здесь не является родным).

Иными словами, C++ не гарантирует точное содержание того, что вы получаете с помощью what(). what() вы видите what(), как вы говорите.

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

+1

Учитывая, что 'TestClass' наследует' std :: runtime_error', он может просто избежать переопределения 'what()' - 'std :: runtime_error :: what()' уже возвращает сообщение, переданное его конструктору. –

+0

@MatteoItalia Я только что заметил это и дал ему попробовать до вашего комментария из вашего объяснения, и он делает то, что я ожидал сейчас. Спасибо за вашу помощь. – Boardy

0

Вам нужен способ указать настраиваемое сообщение об ошибке для std :: exception, для которого afaik не разрешен. См. this для возможного решения.

8

Вы должны собственная реализация какого метода() или использовать std::runtime_error::what(), как написано в комментариях

Скажи:

class TestClass : public std::runtime_error 
{ 
    std::string what_message; 
public: 
    const char* what() override 
    { 
     return what_message.c_str(); 
    } 
}; 

Кроме того, лучше использовать noexcept вместо throw() и только после того, как вы читали о них - link.

И в вашей примерке улове:

catch (const TestClass& myException) 

Вместо catch(TestClass myException) - в противном случае вы неявная копию, которая потенциально может привести в броске исключения. Он также разрушает полиморфизм: если вы хотите использовать экземпляр реализации catchpure virtual interface, вам нужно будет использовать ссылку.

+0

. О, хорошо знать спасибо, спасибо за дополнительную информацию. – Boardy