tags:

views:

88

answers:

1
#include <iostream>
using namespace std;

class A{
public:
    A() {std::cout<<"A() ";}
    A(const A& a){cout<<"A(const A&) ";}
    ~A(){cout<<"~A() ";}

    virtual void Foo(){cout<<"A::Foo() ";}
};

class B: public A
{
public:
    B(){std::cout<<"B() ";}
    B(const B& a){cout<<"B(const B&) ";}
    ~B(){cout<<"~B() ";}

    virtual void Foo() {cout<<"B::Foo() ";}

};

int main()
{
    try{
         B b;
         throw b;                        //throw like this
    }
    catch(A ex){
        ex.Foo();
    }
    catch(B ex){
        ex.Foo();
    }
    catch(A * ex){
        ex->Foo();
    }
    catch(B * ex){
        ex->Foo();
    }

    return 0;
}

The output is

A() B() A() B(const B&) ~B() ~A() A(const A&) A::Foo() ~A() ~B() ~A()

#include <iostream>
using namespace std;

class A{
public:
    A() {std::cout<<"A() ";}
    A(const A& a){cout<<"A(const A&) ";}
    ~A(){cout<<"~A() ";}

    virtual void Foo(){cout<<"A::Foo() ";}
};

class B: public A
{
public:
    B(){std::cout<<"B() ";}
    B(const B& a){cout<<"B(const B&) ";}
    ~B(){cout<<"~B() ";}

    virtual void Foo() {cout<<"B::Foo() ";}

};

int main()
{
    try{

         throw B();              //throw it this way
    }
    catch(A ex){
        ex.Foo();
    }
    catch(B ex){
        ex.Foo();
    }
    catch(A * ex){
        ex->Foo();
    }
    catch(B * ex){
        ex->Foo();
    }

    return 0;
}

The output is

A() B() A(const A&) A::Foo() ~A() ~B() ~A()

Can anybody explain the difference to me? The difference is

A() B(const B&) ~B() ~A()

Why is the copy constructor of class B invoked?

Thanks so much!

+4  A: 

Because in the first sample the local variable b is first being copied at the throw line, and then sliced at the catch ( A ex ) line, while in the second sample only the second copy is performed.

I think I have to mention the throw by value, catch by reference mantra here :)

Nikolai N Fetissov
then why the constructor of A is called first before the copy constructor of class B?
skydoor
Base constructor always gets called before one of the derived class. That's why you can't call virtual functions (and expect derived code to run) in base ctor/dtor.
Nikolai N Fetissov
Because B's copy constructor doesn't explicitly copy the base, so the base is default-constructed. `B(const B}` GCC warns both about this behavior and that the handler for A will catch the exception before handler for B gets a chance.
UncleBens
@skydoor: because B's copy ctor still has to construct the `A` part of the object, and you didn't have anything in the initializer list for the copy ctor to tell it how to construct the `A` part of the object, so it used the default constructor for `A`.
Michael Burr