抛出关键字的用法
Usage of throw keyword
我最近开始用C++编码,我对以下代码有疑问。我在使用"投掷"关键字时遇到问题。在中位数或等级函数中,它什么时候会给出误差?投掷和domain_error的确切用途是什么?我是否会从成绩或中位数函数收到错误消息?
#include<iostream>
#include<string>
#include<vector>
#include<iomanip>
#include<ios>
#include<algorithm>
#include<stdexcept>
using std::cout; using std::cin;
using std::vector; using std::endl;
using std::string; using std::streamsize;
using std::setprecision; using std::domain_error;
using std::istream;
double grade(double midterm, double final, double homework)
{
return 0.2*midterm+0.4*final+0.4*homework;
}
double median(vector<double> vec)
{
typedef vector<double>::size_type vec_sz;
vec_sz size= vec.size();
if(size==0)
{
throw domain_error("Median of an empty vector"); //when will i get this error msg??
}
sort(vec.begin(),vec.end());
vec_sz mid=size/2;
return size%2==0?(vec[mid]+vec[mid-1])/2:vec[mid];
}
double grade(double midterm, double final, const vector<double>& hw)
{
if(hw.size()==0)
{
throw domain_error("Student has done no homework");// when will i get this error?
}
return grade(midterm, final, median(hw));
}
istream& read_hw(istream& in, vector<double>& hw)
{
if(in)
{
hw.clear();
double x;
while(in>>x)
hw.push_back(x);
in.clear();
}
return in;
}
int main()
{
string name;
cout<<"Please enter your name:";
cin>>name;
cout<<"Hello "<<name<<"!"<<endl;
cout << "Please enter your midterm and final exam grades: ";
double midterm, final;
cin >> midterm >> final;
cout << "Enter all your homework grades, "
"followed by end-of-file: ";
vector<double> homework;
read_hw(cin, homework);
try {
double final_grade = grade(midterm, final, homework);
streamsize prec = cout.precision();
cout << "Your final grade is " << setprecision(3)
<< final_grade << setprecision(prec) << endl;
} catch (domain_error) {
cout << endl << "You must enter your grades. "
"Please try again." << endl;
return 1;
}
return 0;
}
您可以从 catch
语句中的异常中获取消息。
try {
double final_grade = grade(midterm, final, homework);
streamsize prec = cout.precision();
cout << "Your final grade is " << setprecision(3) << final_grade
<< setprecision(prec) << endl;
} catch (const domain_error& error) {
cout << error.what(); // <-- Will print your message.
}
想象一系列相互调用的函数:
A -> B -> C -> D -> E -> F -> G
如果 G
抛出类型 X
的异常,并且 D
是捕获类型 X
的异常的最接近的函数,或者它的父级之一,或...
,则函数G
、F
和 E
将被关闭,D
将捕获异常。
在您的情况下,这两种异常都将被main
捕获:
} catch (domain_error) {
然而,在这个捕手的身体中,你没有做太多有用的事情:
cout << endl << "You must enter your grades. "
"Please try again." << endl;
return 1;
首先,您没有打印随 domain_error
抛出的实际消息。请看薄佩尔松的回答。
其次,如果你想再试一次,你应该把整个主线放在一个循环中,而不是return
,你continue
。
最后,不要将异常视为错误处理的出色方法,它们并不是那么好。
double median(vector<double> vec)
将抛出一个domain_error
,以防传递vec
不包含任何元素。double grade(double midterm, double final, const vector<double>& hw)
会出于同样的原因抛出它 - 如果一个hw
向量为空。
一旦throw domain_error("...")
被执行,median
或grade
将停止其执行,并且控制权将立即传递到最近的相应 catch 块,该块在 main
中catch (domain_error)
。可以使用domain_error
对象的函数what
来检索消息。
} catch (const domain_error& ex) {
cout << ex.what() << endl;
return 1;
}
> throw
关键字意味着如果到达这一行代码(即 if 中的语句为 true),那么它将在堆栈中抛出错误,直到它被捕获。
这是什么意思?这意味着,如果您调用了函数grade
并抛出错误,则有两个选项:
1) 如果对函数的调用位于try and catch
块内,即:
try {
grade();
} catch(domain_error) {
cout << "An error occured" << endl;
}
然后它将捕获它,执行 catch 子句中的内容,程序将继续。
2)如果调用不在 try 和 catch 块内,那么它将递归地弹出调用此函数的函数,直到到达 try 和 catch 块,或者堆栈中没有其他函数。在这种情况下,由于未捕获的异常,它很可能会粉碎(这就是它在 Java 中所做的)。
希望事情清楚了。
另外,请注意,catch 子句中的错误应该与抛出的错误相同,否则,它不会捕获它。
你的问题已经回答了,但关于你写的东西,我想提几件事。
在我个人看来,我认为你在这里使用exception
是完全没有必要的。
您使函数grade
重载,并在此过程中使代码混乱。
您的median
函数通过 value
获取std::vector
参数,其中不需要进行复制(在您的示例中)。
您两次检查具有完全相同内容的两个向量的长度,并引发两个异常。median
中的异常永远不会在您的示例中引发。
所有这些都是可以避免的。
double median(vector<double>& vec)
{
sort(vec.begin(),vec.end());
vec_sz mid = size/2;
return size%2==0?(vec[mid]+vec[mid-1])/2:vec[mid];
}
double grade(double midterm, double final, double homework)
{
return 0.2*midterm+0.4*final+0.4*homework;
}
在您的主要:
if(hw.size())
{
double final_grade = grade(midterm, final, median(hw));
}
else
{
cout << endl << "You must enter your grades. "
"Please try again." << endl;
return 1;
}
@Aesthete .我认为中值函数 shouble 按值获取 std::vector 参数。在加速C++书中,作者解释了原因。
median 函数通过调用 sort 来更改其参数的值。复制参数可防止通过排序所做的更改传回调用方。这种行为是有道理的,因为取向量的中位数不应该改变 vecotr 本身。
如果不喜欢这样,编译此文件时会收到以下错误消息(mingw32-g++.exe)
错误:从类型为"const std::vector"的表达式初始化类型"std::vector&"的引用无效|
错误:在传递"双中位数(std::vector&)"的参数 1 时|
- Visual Studio 2015:Extern "C" 和 "export" 关键字
- C++中的"inline"关键字
- 如何确保C++函数在定义之前声明(如override关键字)
- 这个指针在c++中的用法
- 谷歌模拟和覆盖关键字
- 当C++中需要自动删除时,这是静态的正确用法吗?
- 结构体 S { int align; } 之间的区别;(struct 关键字后的名称)和 struct { int al
- 如果全局变量默认是外部变量,为什么要添加"extern"关键字?
- libstdc++ 文件系统中未初始化的用法?
- lambda 中的跨平台"auto"关键字用法:integral_constant作为函数参数
- "extern"关键字用法
- 常量关键字用法C++
- 抛出关键字的用法
- 在 VC++ 中访问一个文件中声明的变量.(外部关键字用法)
- c++使用Boost库示例中的声明关键字用法
- extern关键字在C++中的用法
- c++关键字new的奇怪用法
- extern关键字和多个翻译单元的用法
- 从语法的角度来看,"volatile"关键字在C++函数中有多少用法?
- 外部关键字用法