Какой тип я должен уловить, если я напишу строковый литерал?

Я пишу довольно простое приложение на С++, используя g++ под Linux, и я пытаюсь перебросить некоторые исходные строки в качестве исключений (да, я знаю, это не очень хорошая практика).

У меня есть следующий код (упрощенный):

int main()
{
  try
  {
    throw "not implemented";

  }
  catch(std::string &error)
  {
    cerr<<"Error: "<<error<<endl;
  }
  catch(char* error)
  {
    cerr<<"Error: "<<error<<endl;
  }
  catch(...)
  {
    cerr<<"Unknown error"<<endl;
  }
}

И я получаю Unknow error на консоли. Но если я статирую буквенную строку для std::string или char *, она печатает Error: not implemented, как и ожидалось. Мой вопрос: так, какой тип я должен поймать, если я не хочу использовать статические приведения?

Ответ 1

Вам нужно поймать его char const* вместо char*. Ничто вроде std::string и char* не поймает его.

В Catching есть ограниченные правила в отношении того, с какими типами они совпадают. Спектр говорит (где "cv" означает "const/volatile combination" или ни один из них).

Обработчик - это соответствие для объекта исключения типа E, если

  • Обработчик имеет тип cv T или cv T & и E и T одного типа (игнорируя cv-квалификаторы верхнего уровня) или
  • обработчик имеет тип cv T или cv T & и T - однозначный публичный базовый класс E, или
  • обработчик имеет тип cv1 T * cv2, а E - тип указателя, который может быть преобразован в тип обработчика одним или обоими

    • стандартное преобразование указателя (4.10), не включающее преобразование указателей в частные или защищенные или неоднозначные классы
    • квалификационное преобразование

Строковый литерал имеет тип char const[N], но бросание массива будет распадать массив и на самом деле бросает указатель на его первый элемент. Таким образом, вы не можете поймать поток строк с текстом char*, потому что в то время, когда он совпадает, ему нужно сопоставить char* с char const*, который отбрасывает const (преобразование квалификации разрешено добавлять только Const). Специальное преобразование строкового литерала в char* рассматривается только тогда, когда вам нужно специально преобразовать строковый литерал.

Ответ 2

Попробуйте добавить const к типам, которые вы ловите, const char* (возможно const char* const).

Ответ 3

Точный тип строкового литерала - это массив константных символов (const char [15] для вашего примера, поскольку включен терминатор NUL).

Ответ 4

Тип должен быть const char[15] или const char*.

Однако, хотя язык не запрещает вам бросать какое-либо значение типа, вы не должны воспитывать собственные типы данных в качестве исключения. Вместо этого вы хотите создать экземпляр std::exception() или создать свой собственный класс исключений.

Ответ 5

Проблема в том, что вы пытаетесь поймать что-то, что является константой. Будет работать следующее:

 catch (const char * ошибка) {   сегг

Ответ 6

Тип строкового литерала char const *. Там (устаревшее) преобразование в char * предусмотрено для обратной совместимости с существующим кодом (но вы все равно должны рассматривать его как const - любая попытка модификации дает UB).

Как таковой, такой код должен работать:

#include <iostream>
using namespace std;

int main()
{
  try
  {
    throw "not implemented";

  }
  catch(char const *error)
  {
    cerr<<"Error: "<<error<<endl;
  }
  return 0;
}

Ответ 7

Ознакомьтесь с разделом 2.14.5 стандартной спецификации, он рассматривает типы и виды строковых литералов на 3 страницах. Не делайте то, что вы начали делать, просто скажите:

throw std::exception("not implemented");

вместе с собственным

catch (std::exception& pEx)

Что-то не так с этим "нормальным" подходом...?