exception catch

Discussion in 'C++' started by Rahul, Dec 8, 2007.

  1. Rahul

    Rahul Guest

    Hi Everyone,

    I have the following exception class,

    class E1
    {
    };

    class E2
    {
    public: E2(const E1&)
    {
    printf("automatic type conversion\n");
    }
    };

    int main()
    {
    try
    {
    throw E1();
    }
    catch(E2 obj)
    {
    printf("first handler\n");
    }
    catch(E1 obj1)
    {
    printf("second handler\n");
    }
    }

    IN the above case, the E1 object is not converted into E2 and is
    handled by the second handler, this suggests that automatic type
    conversion doesn't happen with exceptions, i was wondering if this is
    specified in standards and is there any reason for that?

    Thanks in advance!!!
     
    Rahul, Dec 8, 2007
    #1
    1. Advertising

  2. Rahul

    Ian Collins Guest

    Rahul wrote:
    > Hi Everyone,
    >
    > I have the following exception class,
    >
    > class E1
    > {
    > };
    >
    > class E2
    > {
    > public: E2(const E1&)
    > {
    > printf("automatic type conversion\n");
    > }
    > };
    >
    > int main()
    > {
    > try
    > {
    > throw E1();
    > }
    > catch(E2 obj)


    Don't catch exceptions by value, use a const reference.

    --
    Ian Collins.
     
    Ian Collins, Dec 8, 2007
    #2
    1. Advertising

  3. Rahul

    Kai-Uwe Bux Guest

    Rahul wrote:

    > Hi Everyone,
    >
    > I have the following exception class,
    >
    > class E1
    > {
    > };
    >
    > class E2
    > {
    > public: E2(const E1&)
    > {
    > printf("automatic type conversion\n");
    > }
    > };
    >
    > int main()
    > {
    > try
    > {
    > throw E1();
    > }
    > catch(E2 obj)
    > {
    > printf("first handler\n");
    > }
    > catch(E1 obj1)
    > {
    > printf("second handler\n");
    > }
    > }
    >
    > IN the above case, the E1 object is not converted into E2 and is
    > handled by the second handler, this suggests that automatic type
    > conversion doesn't happen with exceptions, i was wondering if this is
    > specified in standards and is there any reason for that?


    It is specified in [15.3/3].

    As for a reason, I can only guess. However, I would conjecture that the
    problem is that when you throw, you do not necessarily have control over
    the catch. I.e., a library component might throw precisely because it
    cannot handle the condition locally and wants the client code to supply a
    catch handler. If you allowed for user-defined conversions in this setting,
    there could be surprise catch-matches.


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Dec 8, 2007
    #3
  4. In article
    <>,
    Rahul <> wrote:

    > Hi Everyone,
    >
    > I have the following exception class,
    >
    > class E1
    > {
    > };
    >
    > class E2
    > {
    > public: E2(const E1&)
    > {
    > printf("automatic type conversion\n");
    > }
    > };
    >
    > int main()
    > {
    > try
    > {
    > throw E1();
    > }
    > catch(E2 obj)
    > {
    > printf("first handler\n");
    > }
    > catch(E1 obj1)
    > {
    > printf("second handler\n");
    > }
    > }
    >
    > IN the above case, the E1 object is not converted into E2 and is
    > handled by the second handler, this suggests that automatic type
    > conversion doesn't happen with exceptions, i was wondering if this is
    > specified in standards and is there any reason for that?


    That is correct, according to 15.3. In my opinion, this is a desired
    behavior, as exception handlers are meant to handle specific exceptions,
    not simply any exception that can be conveniently converted. Imagine the
    confusion when you have a more-appropriate exception handler higher up
    the call tree, and some other exception handler down below preempts it
    due to automatic type conversion.

    Note that exception handlers will handle an exception if it is a derived
    class of its parameter type.

    -dr
     
    Dave Rahardja, Dec 8, 2007
    #4
  5. Rahul

    Rahul Guest

    On Dec 8, 4:04 pm, Ian Collins <> wrote:
    > Rahul wrote:
    > > Hi Everyone,

    >
    > > I have the following exception class,

    >
    > > class E1
    > > {
    > > };

    >
    > > class E2
    > > {
    > > public: E2(const E1&)
    > > {
    > > printf("automatic type conversion\n");
    > > }
    > > };

    >
    > > int main()
    > > {
    > > try
    > > {
    > > throw E1();
    > > }
    > > catch(E2 obj)

    >
    > Don't catch exceptions by value, use a const reference.
    >
    > --
    > Ian Collins.


    Why do you say that exception's should be caught by value?
    is it because of object slicing when a derived class exception is
    caught by a base class exception handler?
     
    Rahul, Dec 9, 2007
    #5
  6. * Rahul:
    > On Dec 8, 4:04 pm, Ian Collins <> wrote:
    >> Rahul wrote:
    >>> Hi Everyone,
    >>> I have the following exception class,
    >>> class E1
    >>> {
    >>> };
    >>> class E2
    >>> {
    >>> public: E2(const E1&)
    >>> {
    >>> printf("automatic type conversion\n");
    >>> }
    >>> };
    >>> int main()
    >>> {
    >>> try
    >>> {
    >>> throw E1();
    >>> }
    >>> catch(E2 obj)

    >> Don't catch exceptions by value, use a const reference.
    >>
    >> --
    >> Ian Collins.

    >
    > Why do you say that exception's should be caught by value?
    > is it because of object slicing when a derived class exception is
    > caught by a base class exception handler?


    On reason is to avoid copy construction.

    Consider the case where the copy constructor might trow (e.g. allocating
    a string).

    A copy construction exception at the throw point is bad but at least you
    do get an exception -- just not necessarily the one you asked for --
    but a copy construction exception at catch point is t r o u b l e.

    Another reason is efficiency, avoiding the possible copying.

    And a third reason is clarity: by catching by reference to const you're
    telling the reader of the source code that you're not going to modify
    this exception object, and you don't need it copied.

    Since catching by reference to const is the most common idiom, anything
    else indicates that for some reason you need something else.

    Cheers, & hth.,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Dec 9, 2007
    #6
  7. On Dec 9, 10:34 am, "Alf P. Steinbach" <> wrote:
    > * Rahul:
    >
    >
    >
    >
    >
    > > On Dec 8, 4:04 pm, Ian Collins <> wrote:
    > >> Rahul wrote:
    > >>> Hi Everyone,
    > >>> I have the following exception class,
    > >>> class E1
    > >>> {
    > >>> };
    > >>> class E2
    > >>> {
    > >>> public: E2(const E1&)
    > >>> {
    > >>> printf("automatic type conversion\n");
    > >>> }
    > >>> };
    > >>> int main()
    > >>> {
    > >>> try
    > >>> {
    > >>> throw E1();
    > >>> }
    > >>> catch(E2 obj)
    > >> Don't catch exceptions by value, use a const reference.

    >
    > >> --
    > >> Ian Collins.

    >
    > > Why do you say that exception's should be caught by value?
    > > is it because of object slicing when a derived class exception is
    > > caught by a base class exception handler?

    >
    > On reason is to avoid copy construction.
    >
    > Consider the case where the copy constructor might trow (e.g. allocating
    > a string).
    >
    > A copy construction exception at the throw point is bad but at least you
    > do get an exception -- just not necessarily the one you asked for --
    > but a copy construction exception at catch point is t r o u b l e.


    Aren't exceptions thrown always copied (atleast once) after they are
    thrown and before they are caught? To make it persistent during the
    stack unwinding? And if copy construction can throw, it is a problem
    even before catching the exception. I think the most important reason
    for not catching exceptions by value is efficiency i.e. we avoid
    atleast one copy creation of the exception object.

    The other reason could be writing a generic base exception handler
    where all derived types can be caught without slicing.
     
    Abhishek Padmanabh, Dec 9, 2007
    #7
  8. Rahul

    Rahul Guest

    On Dec 9, 11:27 am, Abhishek Padmanabh <>
    wrote:
    > On Dec 9, 10:34 am, "Alf P. Steinbach" <> wrote:
    >
    >
    >
    > > * Rahul:

    >
    > > > On Dec 8, 4:04 pm, Ian Collins <> wrote:
    > > >> Rahul wrote:
    > > >>> Hi Everyone,
    > > >>> I have the following exception class,
    > > >>> class E1
    > > >>> {
    > > >>> };
    > > >>> class E2
    > > >>> {
    > > >>> public: E2(const E1&)
    > > >>> {
    > > >>> printf("automatic type conversion\n");
    > > >>> }
    > > >>> };
    > > >>> int main()
    > > >>> {
    > > >>> try
    > > >>> {
    > > >>> throw E1();
    > > >>> }
    > > >>> catch(E2 obj)
    > > >> Don't catch exceptions by value, use a const reference.

    >
    > > >> --
    > > >> Ian Collins.

    >
    > > > Why do you say that exception's should be caught by value?
    > > > is it because of object slicing when a derived class exception is
    > > > caught by a base class exception handler?

    >
    > > On reason is to avoid copy construction.

    >
    > > Consider the case where the copy constructor might trow (e.g. allocating
    > > a string).

    >
    > > A copy construction exception at the throw point is bad but at least you
    > > do get an exception -- just not necessarily the one you asked for --
    > > but a copy construction exception at catch point is t r o u b l e.

    >
    > Aren't exceptions thrown always copied (atleast once) after they are
    > thrown and before they are caught? To make it persistent during the
    > stack unwinding? And if copy construction can throw, it is a problem
    > even before catching the exception. I think the most important reason
    > for not catching exceptions by value is efficiency i.e. we avoid
    > atleast one copy creation of the exception object.
    >
    > The other reason could be writing a generic base exception handler
    > where all derived types can be caught without slicing.


    Yes i think so, they are copied atleast once, and this code
    illustrates the same,

    class E
    {
    public : E()
    {
    printf("in default constructor...\n");
    }
    E(const E& ref)
    {
    printf("copy constructor is invoked...\n");
    }
    };

    int main()
    {
    try
    {
    printf("in try\n");
    throw E();
    }
    catch(E& ref)
    {
    printf("in handler\n");
    }
    return(0);
    }

    output is

    in try
    in default constructor...
    copy constructor is invoked...
    in handler
    Press any key to continue
     
    Rahul, Dec 9, 2007
    #8
  9. On 2007-12-09 00:56, Dave Rahardja wrote:
    > In article
    > <>,
    > Rahul <> wrote:
    >
    >> Hi Everyone,
    >>
    >> I have the following exception class,
    >>
    >> class E1
    >> {
    >> };
    >>
    >> class E2
    >> {
    >> public: E2(const E1&)
    >> {
    >> printf("automatic type conversion\n");
    >> }
    >> };
    >>
    >> int main()
    >> {
    >> try
    >> {
    >> throw E1();
    >> }
    >> catch(E2 obj)
    >> {
    >> printf("first handler\n");
    >> }
    >> catch(E1 obj1)
    >> {
    >> printf("second handler\n");
    >> }
    >> }
    >>
    >> IN the above case, the E1 object is not converted into E2 and is
    >> handled by the second handler, this suggests that automatic type
    >> conversion doesn't happen with exceptions, i was wondering if this is
    >> specified in standards and is there any reason for that?

    >
    > That is correct, according to 15.3. In my opinion, this is a desired
    > behavior, as exception handlers are meant to handle specific exceptions,
    > not simply any exception that can be conveniently converted. Imagine the
    > confusion when you have a more-appropriate exception handler higher up
    > the call tree, and some other exception handler down below preempts it
    > due to automatic type conversion.


    That would never happen since the handlers are tried top down for a
    match and the first match is used. So if an exact match is above one
    that would require a conversion the exact match would always be used.

    I believe that what you were thinking of was the reverse, when the
    handler requiring a conversion was placed above the exact match, in
    which case the match requiring a conversion would be used. Notice that
    this can happen if you have a handler taking a base-class above a
    handler for a derived class, the handler for the derived class would
    never be used.

    --
    Erik Wikström
     
    Erik Wikström, Dec 9, 2007
    #9
  10. Rahul

    James Kanze Guest

    On Dec 9, 7:27 am, Abhishek Padmanabh <>
    wrote:
    > On Dec 9, 10:34 am, "Alf P. Steinbach" <> wrote:
    > > * Rahul:


    > > > On Dec 8, 4:04 pm, Ian Collins <> wrote:
    > > >> Rahul wrote:
    > > >>> Hi Everyone,
    > > >>> I have the following exception class,
    > > >>> class E1
    > > >>> {
    > > >>> };
    > > >>> class E2
    > > >>> {
    > > >>> public: E2(const E1&)
    > > >>> {
    > > >>> printf("automatic type conversion\n");
    > > >>> }
    > > >>> };
    > > >>> int main()
    > > >>> {
    > > >>> try
    > > >>> {
    > > >>> throw E1();
    > > >>> }
    > > >>> catch(E2 obj)


    Concerning the original question: basically, the only
    conversions considered are derived to base, and then only if the
    base is an unambiguous public base. (In the case of pointers,
    the conversion to void* is also considered---but you shouldn't
    be throwing pointers---and in all cases, top level cv qualifiers
    are ignored. And I think a few very, very basic conversions
    also take place systematically: array to pointer, for example.)

    > > >> Don't catch exceptions by value, use a const reference.
    > > > Why do you say that exception's should be caught by value?
    > > > is it because of object slicing when a derived class exception is
    > > > caught by a base class exception handler?


    > > On reason is to avoid copy construction.


    > > Consider the case where the copy constructor might trow (e.g. allocating
    > > a string).


    > > A copy construction exception at the throw point is bad but at least you
    > > do get an exception -- just not necessarily the one you asked for --
    > > but a copy construction exception at catch point is t r o u b l e.


    > Aren't exceptions thrown always copied (atleast once) after they are
    > thrown and before they are caught? To make it persistent during the
    > stack unwinding? And if copy construction can throw, it is a problem
    > even before catching the exception.


    The formal semantics of a throw is copy initialization of the
    exception somewhere where it won't disappear. As always with
    copy initialization, there must be an accessible copy
    constructor, and as always, the compiler is allowed to elide the
    copy constructor.

    The exception is not considered as being thrown until this copy
    is finished, however. If the copy triggers an exception, that
    exception will be thrown, rather than the original exception.
    The exception is not considered caught until the code in the
    catch block is entered, after the copy (if the catch is by
    value). And exception in this copy will cause terminate to be
    called.

    > I think the most important reason
    > for not catching exceptions by value is efficiency i.e. we avoid
    > atleast one copy creation of the exception object.


    Given all the rest that happes when you throw an exception, this
    is not normally an issue.

    > The other reason could be writing a generic base exception handler
    > where all derived types can be caught without slicing.


    That's probably the original motivation behind the rule to catch
    by reference. As Alf pointed out, however, catch by reference
    has become the "normal" way of doing things in C++; anytime you
    do something else, the reader will wonder why. So even if
    you're throwing a non-polymorphic object, you should still catch
    by reference.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Dec 10, 2007
    #10
  11. Rahul

    James Kanze Guest

    On Dec 9, 9:20 am, Rahul <> wrote:
    > On Dec 9, 11:27 am, Abhishek Padmanabh
    > <> wrote:


    [...]
    > Yes I think so, they are copied atleast once, and this code
    > illustrates the same,


    > class E
    > {
    > public : E()
    > {
    > printf("in default constructor...\n");
    > }
    > E(const E& ref)
    > {
    > printf("copy constructor is invoked...\n");
    > }
    > };


    > int main()
    > {
    > try
    > {
    > printf("in try\n");
    > throw E();
    > }
    > catch(E& ref)
    > {
    > printf("in handler\n");
    > }
    > return(0);
    > }


    > output is


    > in try
    > in default constructor...
    > copy constructor is invoked...
    > in handler
    > Press any key to continue


    This depends on the compiler. The compiler is allowed to elide
    the copy, and all of the compilers I have access to (g++, Sun CC
    and VC++) do (and don't output the line "copy constructor is
    invoked..."). (This depends on the version, however---older
    versions of g++ did call the copy constructor here.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Dec 10, 2007
    #11
  12. Rahul

    James Kanze Guest

    On Dec 8, 12:42 pm, Kai-Uwe Bux <> wrote:
    > Rahul wrote:


    [...]
    > > IN the above case, the E1 object is not converted into E2 and is
    > > handled by the second handler, this suggests that automatic type
    > > conversion doesn't happen with exceptions, i was wondering if this is
    > > specified in standards and is there any reason for that?


    > It is specified in [15.3/3].


    > As for a reason, I can only guess. However, I would conjecture that the
    > problem is that when you throw, you do not necessarily have control over
    > the catch. I.e., a library component might throw precisely because it
    > cannot handle the condition locally and wants the client code to supply a
    > catch handler. If you allowed for user-defined conversions in this setting,
    > there could be surprise catch-matches.


    Implementation considerations may also have played a role.
    Remember that the type matching here takes place at runtime (and
    so must use some form of RTTI). Derived to base is pretty
    straight foreward to do dynamically, but anything else would
    require a lot more information in the RTTI structures, and a lot
    more work to process it. (Off hand, except for Derived to Base,
    the only other conversion which needs to be considered
    dynamically is pointer to void*.)

    Note that some conversions occur at the throw site,
    systematically, and thus do not require RTTI to support them.
    Array to pointer, for example: you can declare a catch with a
    reference to an array:
    catch ( int const (&array)[ 5 ] )
    for example, but there's nothing you can throw that will match
    it, because the array will be converted to a pointer at the
    throw site, before matching starts.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Dec 10, 2007
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. eddie wang

    ASP catch exception

    eddie wang, Jul 24, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    4,468
    eddie wang
    Jul 24, 2003
  2. Franck

    How to catch COM exception in .Net

    Franck, Aug 6, 2003, in forum: ASP .Net
    Replies:
    1
    Views:
    565
    Natty Gur
    Aug 7, 2003
  3. John Black
    Replies:
    8
    Views:
    4,214
    Xenos
    Aug 20, 2004
  4. Adam
    Replies:
    9
    Views:
    612
    red floyd
    Feb 2, 2006
  5. Marteno Rodia

    catch doesn't catch a thrown exception

    Marteno Rodia, Aug 3, 2009, in forum: Java
    Replies:
    5
    Views:
    623
    Daniel Pitts
    Aug 5, 2009
Loading...

Share This Page