What type should I catch if I throw a string liter

2019-01-23 02:37发布

I am writing a pretty simple application in C++ using g++ under Linux and I am trying to throw some raw strings as exceptions (yes, I know, its not a good practise).

I have the following code (simplified):

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

And I get Unknow error on the console. But if I static cast the literal string to either std::string or char * it prints Error: not implemented as expected. My question is: so what is the type I should catch if I don't want to use static casts?

7条回答
老娘就宠你
2楼-- · 2019-01-23 03:10

Try adding const to the types you're catching, const char* (possibly const char* const).

查看更多
等我变得足够好
3楼-- · 2019-01-23 03:13

You need to catch it with char const* instead of char*. Neither anything like std::string nor char* will catch it.

Catching has restricted rules with regard to what types it match. The spec says (where "cv" means "const/volatile combination" or neither of them).

A handler is a match for an exception object of type E if

  • The handler is of type cv T or cv T& and E and T are the same type (ignoring the top-level cv-qualifiers), or
  • the handler is of type cv T or cv T& and T is an unambiguous public base class of E, or
  • the handler is of type cv1 T* cv2 and E is a pointer type that can be converted to the type of the handler by either or both of

    • a standard pointer conversion (4.10) not involving conversions to pointers to private or protected or ambiguous classes
    • a qualification conversion

A string literal has type char const[N], but throwing an array will decay the array and actually throws a pointer to its first element. So you cannot catch a thrown string literal by a char*, because at the time it matches, it needs to match the char* to a char const*, which would throw away a const (a qualification conversion is only allowed to add const). The special conversion of a string literal to char* is only considered when you need to convert a string literal specifically.

查看更多
我只想做你的唯一
4楼-- · 2019-01-23 03:13

Check out the section 2.14.5 of the standard specification, it treats types and kinds of string literals on 3 pages. Don't do what you started to do, just say:

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

along with proper

catch (std::exception& pEx)

Is there something wrong with this "normal" approach...?

查看更多
萌系小妹纸
5楼-- · 2019-01-23 03:21

The problem is that you're trying to catch something that is a const. The following will work:

catch(const char* error) { cerr
查看更多
男人必须洒脱
6楼-- · 2019-01-23 03:22

The exact type of a string literal is an array of const characters (const char [15] for your example, since the NUL terminator is included). The array decays to const char* when thrown, which is independent of the length.

查看更多
我欲成王,谁敢阻挡
7楼-- · 2019-01-23 03:22

The type of a string literal is char const *. There's a (deprecated) conversion to char * provided for backward compatibility with existing code (but you still have to treat it as const -- any attempt at modification gives UB).

As such, code like this should work:

#include <iostream>
using namespace std;

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

  }
  catch(char const *error)
  {
    cerr<<"Error: "<<error<<endl;
  }
  return 0;
}
查看更多
登录 后发表回答