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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4831523/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 02:40:29  来源:igfitidea点击:

What type should I catch if I throw a string literal?

c++linuxexceptiong++

提问by Grzenio

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 erroron the console. But if I static cast the literal string to either std::stringor char *it prints Error: not implementedas expected. My question is: so what is the type I should catch if I don't want to use static casts?

我进入Unknow error控制台。但是,如果我将文字字符串静态转换为std::string或按预期char *打印Error: not implemented。我的问题是:如果我不想使用静态强制转换,我应该捕获什么类型?

采纳答案by Johannes Schaub - litb

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

你需要用char const*而不是char*. 既不会像std::stringchar*不会抓住它。

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

  • 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

处理程序与类型 E 的异常对象匹配,如果

  • 处理程序的类型为 cv T 或 cv T& 并且 E 和 T 是相同类型(忽略顶级 cv 限定符),或
  • 处理程序的类型为 cv T 或 cv T& 并且 T 是 E 的明确公共基类,或
  • 处理程序的类型为 cv1 T* cv2 并且 E 是一个指针类型,可以通过以下任一或两者转换为处理程序的类型

    • 标准指针转换 (4.10) 不涉及到指向私有或受保护或模糊类的指针的转换
    • 资格转换

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 addconst). The special conversion of a string literal to char*is only considered when you need to convert a string literal specifically.

字符串文字具有 type char const[N],但抛出数组会衰减数组并实际上抛出指向其第一个元素的指针。所以你不能通过 a 捕获抛出的字符串文字char*,因为在它匹配时,它需要将 the 匹配char*到 a char const*,这将丢弃一个 const (限定转换只允许添加const )。char*仅当您需要专门转换字符串文字时才考虑将字符串文字特殊转换为。

回答by luke

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

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

回答by Ben Voigt

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.

字符串文字的确切类型是一个 const 字符数组(const char [15]对于您的示例,因为包含 NUL 终止符)。数组衰减到const char*抛出时,与长度无关。

回答by vz0

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

类型应该是const char[15]or 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()实例,或创建您自己的异常类。

回答by Wes Hardaker

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

问题是你试图捕捉一个常量。以下将起作用:

catch(const char* error) { cerr

回答by Jerry Coffin

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

回答by Paul Michalik

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

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