C++ 异常处理+;如果异常方法在同一类中不起作用,则多态性不起作用
我正在尝试这样的代码C++ 异常处理+;如果异常方法在同一类中不起作用,则多态性不起作用,c++,exception,polymorphism,virtual-functions,throw,C++,Exception,Polymorphism,Virtual Functions,Throw,我正在尝试这样的代码 //A.hpp class A{ public: A() {} virtual const char *message() const {return "A ERROR";} }; //B.hpp #include "A.hpp" class B:public A { public: B() {} const char *message() const {return "B ERROR";
//A.hpp
class A{
public:
A() {}
virtual const char *message() const {return "A ERROR";}
};
//B.hpp
#include "A.hpp"
class B:public A {
public:
B() {}
const char *message() const {return "B ERROR";}
};
//main.cpp
#include "A.hpp"
#include "B.hpp"
void foo(const A& a) {
/* case 1 */ throw a; /* (or) */ /* case 2 */ throw B(); // LINE 100
}
int main() {
B b;
A &a(b);
b.message(); // OUTPUT: B ERROR
try {
foo(a);
} catch (const A& a) {
std::cout<<"EXCEPTION CALLED "<<a.message()<<std::endl;
}
return 0;
}
//A.hpp
甲级{
公众:
A(){}
虚拟常量char*message()常量{返回“错误”;}
};
//水电站
#包括“A.hpp”
B类:公共A{
公众:
B(){}
常量字符*消息()常量{返回“B错误”;}
};
//main.cpp
#包括“A.hpp”
#包括“B.hpp”
void foo(施工图A&A){
/*案例1*/throw a;//*(或)*//*案例2*/throw B();//第100行
}
int main(){
B B;
A&A(b);
b、 message();//输出:b错误
试一试{
傅(甲),;
}捕获(常数A和A){
std::cout抛出副本变量。foo中的抛出a
实际上并没有从main中抛出对a
的引用,它实际上抛出了a
的副本。在catch语句中,您是通过引用捕获该副本。因为在foo中,a
是对a
的引用,所以副本将对象切片,并且它是出现一个A
,因此失去了它曾经是B
的事实,因为在抛出之前复制了一个对象
即使foo
的参数a
在运行时指向B
的实例,重要的是抛出表达式的编译时类型。因此,实际上,B
的实例被传递给a
(这是合法的,因为B
继承A
)和创建并抛出的新A
实例
复制的原因是,只要有任何catch
块可以捕获异常对象,编译器就必须保证异常对象的生存期。因此,它不能冒堆栈对象“从堆栈边缘脱落”的风险或者堆对象被堆栈展开期间调用的某个析构函数释放。我很难准确理解您的要求,但是。。。
首先,不要将catch的变量命名为与局部变量相同的名称,也就是说,您两次使用“a”来表示不同的事物。您可能会认为通过引用捕获的项是传递到foo中的a,如果foo()抛出B,则不会是真的。为了清楚起见,请将catch更改为
catch (const A& ex)
{
...ex.message()...
}
我怀疑发生的情况是,当在try之外声明时,a仍在范围内,并且a.message()调用局部变量a。如果在try中声明,a不再在catch的作用域中,因此通过引用捕获的a将调用其消息。更改catch的变量名称将删除看似不明确的行为。为了完整性,我觉得ed指出,就像虚拟复制(也称为克隆)解决了通过基复制一样,虚拟(重新)抛出解决了通过基抛出:
struct base {
virtual void
rethrow() const
{ throw *this; }
// it's also usual to make the base type abstract
// so that users can't slice, e.g. boost::exception
// it's also possible to make copying protected
};
struct derived: base {
void
rethrow() const override
{ throw *this; }
};
void
foo(base const& b)
{
// no: slices
// throw b;
b.rethrow(); // Ok
}
无论使用哪个a
,两者都不应该显示观察到的消息。我无法从问题中准确判断在什么条件下抛出了什么。我只是在最后一句中注意到,如果在try内部或外部声明a,则会有不同的行为。因为没有理由重用变量名“a”像这样,对我来说,清理这件事似乎是明智的。不知道为什么有人认为这是个坏主意。否决票不是因为你的建议不好,(这是个好建议),而是因为这不是问题的答案。