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
aoffoopoints to an instance ofBat run-time, what matters is the compile-time type of the throw expression. So, effectively, the instance ofBis passed to the copy-constructor ofA(which is legitimate sinceBinheritsA) and a newAinstance 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
catchblock 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.