如果我抛出一个字符串文字,我应该捕获什么类型?

时间:2021-02-16 16:38:24

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).

我正在使用Linux下的g++编写一个相当简单的c++应用程序,并试图抛出一些原始字符串作为异常(是的,我知道,这不是一个很好的实践)。

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?

我在控制台得到了未知的错误。但是如果我静态地将字串转换为std::string或char*,它会输出错误:没有按预期实现。我的问题是:如果我不想使用静态类型转换,那么应该捕获什么类型?

7 个解决方案

#1


28  

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

您需要用char const*而不是char*来捕获它。任何类似std::string或char*的东西都不能捕获它。

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

捕获对于匹配的类型有限制规则。说明书上说(其中“cv”表示“const/volatile组合”或两者都不表示)。

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

处理程序是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
  • 处理程序的类型是cv T或cv t&e,而T是相同的类型(忽略*的cv限定符),或
  • the handler is of type cv T or cv T& and T is an unambiguous public base class of E, or
  • 处理程序是cv T或cv t&t是一个明确的公共基类E,或。
  • 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

    处理程序是cv1 T* cv2,而E是一个指针类型,它可以被转换为处理程序的类型。

    • a standard pointer conversion (4.10) not involving conversions to pointers to private or protected or ambiguous classes
    • 一种标准的指针转换(4.10),不涉及到指向私有或受保护或不明确类的指针的转换
    • 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.

字符串字面上有类型char const[N],但是抛出一个数组将会衰变该数组,并实际抛出一个指向它的第一个元素的指针。因此不能通过char*捕获抛出的字符串字面量,因为在匹配时,它需要将char*与char const*匹配,这将丢弃const(限定转换仅允许添加const)。只有在需要特定地转换字符串文字时,才会考虑将字符串文字转换为char*。

#2


10  

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

尝试在您正在捕获的类型中添加const, const char*(可能是const char* const)。

#3


3  

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).

字符串文字的确切类型是const字符的数组(对于您的示例,const char[15],因为包含了NUL终止符)。

#4


1  

The type should be const char[15] or const char*.

类型应该是const char[15]或const char*。

However, while the language does not forbids you throwing any type value, you should not be raising native data types as exception. Instead, you want to raise an std::exception() instance, or creating your own exception class.

然而,尽管该语言并不禁止您抛出任何类型值,但您不应该将本机数据类型作为异常提出。相反,您希望引发std::exception()实例,或者创建自己的异常类。

#5


1  

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

问题是,你想要抓住的是某种东西。以下工作:

catch(const char* error) { cerr

#6


1  

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).

字符串文字的类型是char const *。有一个(不赞成的)对char *的转换提供了与现有代码的向后兼容性(但是您仍然必须将它视为const——任何修改的尝试都会产生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;
}

#7


1  

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:

查看标准规范2.14.5节,它处理3页上的字符串类型和类型。不要做你刚开始做的事情,只说:

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

along with proper

随着适当的

catch (std::exception& pEx)

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

这种“正常”方法有什么问题吗?

#1


28  

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

您需要用char const*而不是char*来捕获它。任何类似std::string或char*的东西都不能捕获它。

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

捕获对于匹配的类型有限制规则。说明书上说(其中“cv”表示“const/volatile组合”或两者都不表示)。

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

处理程序是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
  • 处理程序的类型是cv T或cv t&e,而T是相同的类型(忽略*的cv限定符),或
  • the handler is of type cv T or cv T& and T is an unambiguous public base class of E, or
  • 处理程序是cv T或cv t&t是一个明确的公共基类E,或。
  • 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

    处理程序是cv1 T* cv2,而E是一个指针类型,它可以被转换为处理程序的类型。

    • a standard pointer conversion (4.10) not involving conversions to pointers to private or protected or ambiguous classes
    • 一种标准的指针转换(4.10),不涉及到指向私有或受保护或不明确类的指针的转换
    • 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.

字符串字面上有类型char const[N],但是抛出一个数组将会衰变该数组,并实际抛出一个指向它的第一个元素的指针。因此不能通过char*捕获抛出的字符串字面量,因为在匹配时,它需要将char*与char const*匹配,这将丢弃const(限定转换仅允许添加const)。只有在需要特定地转换字符串文字时,才会考虑将字符串文字转换为char*。

#2


10  

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

尝试在您正在捕获的类型中添加const, const char*(可能是const char* const)。

#3


3  

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).

字符串文字的确切类型是const字符的数组(对于您的示例,const char[15],因为包含了NUL终止符)。

#4


1  

The type should be const char[15] or const char*.

类型应该是const char[15]或const char*。

However, while the language does not forbids you throwing any type value, you should not be raising native data types as exception. Instead, you want to raise an std::exception() instance, or creating your own exception class.

然而,尽管该语言并不禁止您抛出任何类型值,但您不应该将本机数据类型作为异常提出。相反,您希望引发std::exception()实例,或者创建自己的异常类。

#5


1  

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

问题是,你想要抓住的是某种东西。以下工作:

catch(const char* error) { cerr

#6


1  

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).

字符串文字的类型是char const *。有一个(不赞成的)对char *的转换提供了与现有代码的向后兼容性(但是您仍然必须将它视为const——任何修改的尝试都会产生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;
}

#7


1  

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:

查看标准规范2.14.5节,它处理3页上的字符串类型和类型。不要做你刚开始做的事情,只说:

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

along with proper

随着适当的

catch (std::exception& pEx)

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

这种“正常”方法有什么问题吗?