为什么要按基数抛出派生的 class 个捕获量?
Why throw at derived class catches by base?
对于下面的代码,结果是 "EA Exception Finished",这意味着尽管我们在派生 class 中抛出它,但它被基 class 捕获了。总是吗?如果是这样,我怎样才能使派生的 class 捕获,从而出现 "EB Exception Finished"?
此外,我无法准确理解 throw EB()
和 catch(EA&)
的含义。 catch(EA&)
是否意味着 catch 块获取 EA object 的引用?
对不起我的无知。如果你能给我推荐一本书或其他关于异常结构的参考资料,那将是很大的帮助。
class EA {};
class EB: public EA {};
void F()
{
throw EB(); // throw at EB().
}
int main()
{
try
{
F();
}
catch(EA&) // caught here??
{
std::cout<<"EA Exception";
}
catch(EB&) // why not me? every time?
{
std::cout<<"EB Exception";
}
std::cout<<" Finished"<<std::endl;
return 0;
}
因为 catch 块按照您声明它们的顺序进行检查。
你先被EA&
赶上了。
EB 源自 EA,因此这是一个有效的捕获,第二个捕获被忽略。
您想首先捕获最多 "specialized" 个异常。因此,如果您切换 catch 块,它应该以另一种方式工作。
catch 语句按顺序检查。 EA&
匹配,所以用了。 EB&
永远无法匹配。你需要把更具体的捕获放在第一位。
catch(EB&) // Will catch
{
std::cout<<"EB Exception";
}
catch(EA&) // and this would catch EA objects that aren't EB.
{
std::cout<<"EA Exception";
}
更改 catch
块的顺序以修复该行为:
#include <iostream>
class EA {};
class EB: public EA {};
void F()
{
throw EB(); // throw at EB().
}
int main()
{
try
{
F();
}
catch(EB&) // why not me? every time?
{
std::cout<<"EB Exception";
}
catch(EA&) // caught here??
{
std::cout<<"EA Exception";
}
std::cout<<" Finished"<<std::endl;
return 0;
}
编译器甚至会警告您:
main.cpp:21:3: warning: exception of type 'EB' will be caught
catch(EB&) // why not me? every time?
^~~~~
main.cpp:17:3: warning: by earlier handler for 'EA'
catch(EA&) // caught here??
^~~~~
如[except.handle](工作草案)中的标准所述:
The handlers for a try block are tried in order of appearance. That makes it possible to write handlers that can never be executed, for example by placing a handler for a derived class after a handler for a corresponding base class.
你就是这么做的。确实很有趣。
反转处理程序以解决问题。
原因:
Upcasting
的派生 class 到基础。因此总是卡在第一个捕获点上。
对于下面的代码,结果是 "EA Exception Finished",这意味着尽管我们在派生 class 中抛出它,但它被基 class 捕获了。总是吗?如果是这样,我怎样才能使派生的 class 捕获,从而出现 "EB Exception Finished"?
此外,我无法准确理解 throw EB()
和 catch(EA&)
的含义。 catch(EA&)
是否意味着 catch 块获取 EA object 的引用?
对不起我的无知。如果你能给我推荐一本书或其他关于异常结构的参考资料,那将是很大的帮助。
class EA {};
class EB: public EA {};
void F()
{
throw EB(); // throw at EB().
}
int main()
{
try
{
F();
}
catch(EA&) // caught here??
{
std::cout<<"EA Exception";
}
catch(EB&) // why not me? every time?
{
std::cout<<"EB Exception";
}
std::cout<<" Finished"<<std::endl;
return 0;
}
因为 catch 块按照您声明它们的顺序进行检查。
你先被EA&
赶上了。
EB 源自 EA,因此这是一个有效的捕获,第二个捕获被忽略。
您想首先捕获最多 "specialized" 个异常。因此,如果您切换 catch 块,它应该以另一种方式工作。
catch 语句按顺序检查。 EA&
匹配,所以用了。 EB&
永远无法匹配。你需要把更具体的捕获放在第一位。
catch(EB&) // Will catch
{
std::cout<<"EB Exception";
}
catch(EA&) // and this would catch EA objects that aren't EB.
{
std::cout<<"EA Exception";
}
更改 catch
块的顺序以修复该行为:
#include <iostream>
class EA {};
class EB: public EA {};
void F()
{
throw EB(); // throw at EB().
}
int main()
{
try
{
F();
}
catch(EB&) // why not me? every time?
{
std::cout<<"EB Exception";
}
catch(EA&) // caught here??
{
std::cout<<"EA Exception";
}
std::cout<<" Finished"<<std::endl;
return 0;
}
编译器甚至会警告您:
main.cpp:21:3: warning: exception of type 'EB' will be caught
catch(EB&) // why not me? every time?
^~~~~
main.cpp:17:3: warning: by earlier handler for 'EA'
catch(EA&) // caught here??
^~~~~
如[except.handle](工作草案)中的标准所述:
The handlers for a try block are tried in order of appearance. That makes it possible to write handlers that can never be executed, for example by placing a handler for a derived class after a handler for a corresponding base class.
你就是这么做的。确实很有趣。
反转处理程序以解决问题。
原因:
Upcasting
的派生 class 到基础。因此总是卡在第一个捕获点上。