Как создать производный класс, который принимает wstring, и вызывать конструктор базового класса, который принимает строку? - PullRequest
0 голосов
/ 01 февраля 2012

Некоторое время назад я обнаружил хитрый трюк в stackoverflow, который показал способ создания производного класса исключений из runtime_error, который принимает wstring в качестве конструктора. Хитрость состояла в том, чтобы инициализировать базу runtime_error с помощью вызова виртуального метода. Вот как это выглядит:

UnknownEx(const std::wstring& s) throw() : m_msg(s), std::runtime_error( what() ) {};

И what() выполняет преобразование (я в порядке с преобразованием с потерями из wstring в строку):

virtual const char* what() const throw() {
    // Convert the wstring data member to a char*.
    const wchar_t* wstr = m_msg.c_str();
    char *str = new char[wcslen(wstr)];
    size_t *charsChanged = 0;
    wcstombs_s(charsChanged, str, sizeof(str), wstr, _TRUNCATE);

    return str; 
}

Это прекрасно компилируется, но когда я пытаюсь его использовать:

throw UnknownEx(L"Test Exception");

Сбой приложения в середине what() при попытке найти длину элемента данных m_msg. При отладке в what(), m_msg еще не был установлен. Кажется, что этот вызов функции в уловке списка инициализатора не работает.

Есть ли способ заставить этот "трюк" работать должным образом, или весь мой подход неверен?

Моя долгосрочная цель: Я просто хотел бы создать производный класс исключений, который может быть перехвачен с помощью catch(exception& ex), но принимает в своем конструкторе wstring.

1 Ответ

3 голосов
/ 01 февраля 2012

Программа аварийно завершает работу, потому что std::runtime_error(what()) выполняется до m_msg(s).Базовые классы инициализируются перед переменными-членами.

Хотя ваш вызов what() в этом случае вызовет переопределение UnknownEx, лучше не вызывать виртуальные функции из конструкторов, поскольку семантика сбивает с толку.

Если вы собираетесь хранить свое сообщение об исключении в своей собственной m_msg переменной-члене, не наследуйте от std::runtime_error;нет смысла хранить строку дважды.Рассмотрите возможность получения непосредственно из std::exception.

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