exception catch

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Rahul

    #1

    exception catch

    Hi Everyone,

    I have the following exception class,

    class E1
    {
    };

    class E2
    {
    public: E2(const E1&)
    {
    printf("automat ic 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!!!
  • Ian Collins

    #2
    Re: exception catch

    Rahul wrote:
    Hi Everyone,
    >
    I have the following exception class,
    >
    class E1
    {
    };
    >
    class E2
    {
    public: E2(const E1&)
    {
    printf("automat ic type conversion\n");
    }
    };
    >
    int main()
    {
    try
    {
    throw E1();
    }
    catch(E2 obj)
    Don't catch exceptions by value, use a const reference.

    --
    Ian Collins.

    Comment

    • Kai-Uwe Bux

      #3
      Re: exception catch

      Rahul wrote:
      Hi Everyone,
      >
      I have the following exception class,
      >
      class E1
      {
      };
      >
      class E2
      {
      public: E2(const E1&)
      {
      printf("automat ic 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

      Comment

      • Dave Rahardja

        #4
        Re: exception catch

        In article
        <9adce868-eb6d-468e-a371-10338ce97a72@i2 9g2000prf.googl egroups.com>,
        Rahul <sam_cit@yahoo. co.inwrote:
        Hi Everyone,
        >
        I have the following exception class,
        >
        class E1
        {
        };
        >
        class E2
        {
        public: E2(const E1&)
        {
        printf("automat ic 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

        Comment

        • Rahul

          #5
          Re: exception catch

          On Dec 8, 4:04 pm, Ian Collins <ian-n...@hotmail.co mwrote:
          Rahul wrote:
          Hi Everyone,
          >
          I have the following exception class,
          >
          class E1
          {
          };
          >
          class E2
          {
          public: E2(const E1&)
          {
          printf("automat ic 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?

          Comment

          • Abhishek Padmanabh

            #6
            Re: exception catch

            On Dec 9, 10:34 am, "Alf P. Steinbach" <al...@start.no wrote:
            * Rahul:
            >
            >
            >
            >
            >
            On Dec 8, 4:04 pm, Ian Collins <ian-n...@hotmail.co mwrote:
            Rahul wrote:
            >Hi Everyone,
            > I have the following exception class,
            >class E1
            >{
            >};
            >class E2
            >{
            >public: E2(const E1&)
            > {
            > printf("automat ic 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.

            Comment

            • Rahul

              #7
              Re: exception catch

              On Dec 9, 11:27 am, Abhishek Padmanabh <abhishek.padma n...@gmail.com>
              wrote:
              On Dec 9, 10:34 am, "Alf P. Steinbach" <al...@start.no wrote:
              >
              >
              >
              * Rahul:
              >
              On Dec 8, 4:04 pm, Ian Collins <ian-n...@hotmail.co mwrote:
              >Rahul wrote:
              >>Hi Everyone,
              >> I have the following exception class,
              >>class E1
              >>{
              >>};
              >>class E2
              >>{
              >>public: E2(const E1&)
              >> {
              >> printf("automat ic 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

              Comment

              • =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=

                #8
                Re: exception catch

                On 2007-12-09 00:56, Dave Rahardja wrote:
                In article
                <9adce868-eb6d-468e-a371-10338ce97a72@i2 9g2000prf.googl egroups.com>,
                Rahul <sam_cit@yahoo. co.inwrote:
                >
                >Hi Everyone,
                >>
                > I have the following exception class,
                >>
                >class E1
                >{
                >};
                >>
                >class E2
                >{
                >public: E2(const E1&)
                > {
                > printf("automat ic 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

                Comment

                • James Kanze

                  #9
                  Re: exception catch

                  On Dec 9, 7:27 am, Abhishek Padmanabh <abhishek.padma n...@gmail.com>
                  wrote:
                  On Dec 9, 10:34 am, "Alf P. Steinbach" <al...@start.no wrote:
                  * Rahul:
                  On Dec 8, 4:04 pm, Ian Collins <ian-n...@hotmail.co mwrote:
                  >Rahul wrote:
                  >>Hi Everyone,
                  >> I have the following exception class,
                  >>class E1
                  >>{
                  >>};
                  >>class E2
                  >>{
                  >>public: E2(const E1&)
                  >> {
                  >> printf("automat ic 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:james.kan ze@gmail.com
                  Conseils en informatique orientée objet/
                  Beratung in objektorientier ter Datenverarbeitu ng
                  9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                  Comment

                  • James Kanze

                    #10
                    Re: exception catch

                    On Dec 9, 9:20 am, Rahul <sam_...@yahoo. co.inwrote:
                    On Dec 9, 11:27 am, Abhishek Padmanabh
                    <abhishek.padma n...@gmail.comw rote:
                    [...]
                    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:james.kan ze@gmail.com
                    Conseils en informatique orientée objet/
                    Beratung in objektorientier ter Datenverarbeitu ng
                    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                    Comment

                    • James Kanze

                      #11
                      Re: exception catch

                      On Dec 8, 12:42 pm, Kai-Uwe Bux <jkherci...@gmx .netwrote:
                      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:james.kan ze@gmail.com
                      Conseils en informatique orientée objet/
                      Beratung in objektorientier ter Datenverarbeitu ng
                      9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                      Comment

                      Working...