插入 >> 运算符重载:从 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: 提供了有效的双精度值,但提供的格式不正确
如果读取对象A
抛出异常,A
处于某种未知状态,B
保持不变。
如果读取对象A
成功但读取对象B
抛出异常,A
处于良好状态,B
处于某些状态未知状态
嗯,错误的格式是抛出异常的地方。但是,如果无法读取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;
}
以下是被认为有效的可能用户输入的示例:
(-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: 提供了有效的双精度值,但提供的格式不正确
如果读取对象
A
抛出异常,A
处于某种未知状态,B
保持不变。如果读取对象
A
成功但读取对象B
抛出异常,A
处于良好状态,B
处于某些状态未知状态嗯,错误的格式是抛出异常的地方。但是,如果无法读取
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;
}