I am trying some code like this
//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;
}
in this case, if I use case 1: throw a; //a is an reference of B b; OUTPUT: A ERROR
case 2: throw B(); // creates new B; OUTPUT: B ERROR
What I don't understand is, why doesn't there is no consistency betweek two cases,
If you pass by reference, all the time, there should be some consistency, If I create a new variable inside the function, that is called in the try block, then it calls the correct virtual method, else it doesn't..... Can anyone tell me the control flow.... Please advise....
Because an object is copied before thrown.
Even if the parameter a
of foo
points to an instance of B
at run-time, what matters is the compile-time type of the throw expression. So, effectively, the instance of B
is passed to the copy-constructor of A
(which is legitimate since B
inherits A
) and a new A
instance created and then thrown.
The reason for copy is that compiler must guarantee the lifetime of the exception object as long as there is any catch
block that could catch it. So, it can't risk a stack object "falling off the stack edge" or heap object being deallocated by some destructor invoked during stack unwinding.