插入 >> 运算符重载:从 cin 中检索对象的 ctor 参数时的异常处理

insertion >> operator overload: exception handling when retrieving object's ctor parameters from cin

以下是被认为有效的可能用户输入的示例:

(-12.444,34.55) (2.0,-44.4444)

... 无效输入,缺少 )

(23.33,-234.5555 (-23.33, 44.1)

Complex.cpp : 构造函数

Complex (double real = 1.0, double imag = 0.0 );

Complex.cpp :异常 class

class Invalid_Mode1_Complex_Value: public std::invalid_argument {

public:
  Invalid_Mode1_Complex_Value():std::invalid_argument("Invalid value for inputting Complex # using Mode 1"){}
};

插入运算符重载:

istream & operator >> (istream & input, Complex & obj) {

  input.ignore(2,'('); // skip over '('

  input >> obj.real_part; // read the real component of the Complex #

  // Process ','
  if (input.peek() == ',') {
    input.get(); // swallow ','
  }
  else {

    input.flags(origFormat); // restore format flags

    input.clear();

    throw Invalid_Mode1_Complex_Value();
  }

  // Process imaginary part

  // read the imaginary component of the Complex #
  input >> obj.imaginary_part;

  // Process ')'
  if (input.peek() == ')') {
    input.get(); // swallow ')'
  }

  else {

    input.flags(origFormat); // restore format flags

    input.clear();

    throw Invalid_Mode1_Complex_Value();
    }

  }
  // restore format flags
  input.flags(origFormat);

  return input; // enables  cin >> a >> b >> c
}

Main.cpp:尝试/捕捉:

Complex A,B; // Create Complex objects: 

// My question is regarding the cascading objects in the try block

cout << "\nEnter 2 Complex numbers in the form \"(real_value,imaginary_value)\" :\n";
try     
{
  cin >> A >> B;
}
catch(const Invalid_Mode1_Complex_Value & invalidMode1Exception) 
{
  cerr << "\nException occurred: " << invalidMode1Exception.what() << endl;
}

我不太明白try块中的异常处理是如何发生的:用插入运算符级联对象。可能会发生哪些情况以及如何实施更好的做法。

A:如果对象A接收到错误的输入
B:如果对象 A 没问题,但是对象 B 收到错误输入
C: 提供了有效的双精度值,但提供的格式不正确

  1. 如果读取对象A抛出异常,A处于某种未知状态,B保持不变。

  2. 如果读取对象A成功但读取对象B抛出异常,A处于良好状态,B处于某些状态未知状态

  3. 嗯,错误的格式是抛出异常的地方。但是,如果无法读取double,流中会残留一些部分,读取格式化会失败。

您应该在读取每个 double 后添加对流状态的检查,以检查是否成功:

input >> obj.real_part;
if (!input) throw Invalid_Mode1_Complex_Value();

您应该阅读 exception safety guarantees。在这里,您可以通过读入某个局部变量,然后仅在读取成功时将其分配给 obj 来为 Complex 提供 strong 异常安全。 (您仍然只在流中提供 basic 异常安全)。

std::stream& operator>> (std::istream& input, Complex& obj) {
    Complex tmp;

    // ...
    input >> tmp.real_part;
    if (!input) throw //...
    // ...

    obj = tmp; // if we got to here, we know tmp is properly formed
    return input;
}