Constructor return value?

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

    Constructor return value?

    OK I know a constructor can't have a return value but is it feasible such that I have a class whereby
    //in MyClass1.
    class MyClass

    MyClass1(){}
    ~MyClass1(){}
    MyClass1(int & Result) {Result = InitMyClass()}

    int InitMyClass()


    //in main.cp

    int main(

    int result
    MyClass theobject(resul t)
    printf("The result of initializing the class is %d", result)


  • Carl Daniel [VC++ MVP]

    #2
    Re: Constructor return value?

    Bonj wrote:[color=blue]
    > OK I know a constructor can't have a return value but is it feasible
    > such that I have a class whereby: //in MyClass1.h
    > class MyClass1
    > {
    > MyClass1(){};
    > ~MyClass1(){};
    > MyClass1(int & Result) {Result = InitMyClass()};
    >
    > int InitMyClass();
    > }
    >
    > //in main.cpp
    >
    > int main()
    > {
    > int result;
    > MyClass theobject(resul t);
    > printf("The result of initializing the class is %d", result);
    > }[/color]

    Of course it's feasible, and perfectly legal.

    The Standard C++ way of indicating failure in a constructor is to throw an
    exception, but there might be reasons sometimes that you don't want to do
    that (the only one that comes to mind is a severe performance constraint -
    exception throwing is expensive).

    -cd


    Comment

    • Simon Trew

      #3
      Re: Constructor return value?

      There is another reason not to throw out of a constructor: you don't know
      how well or badly the object is constructed, so you can't clean up. This is
      most important if the constructor allocates resources (e.g. memory)
      dynamically.

      e.g.

      struct C
      {
      bool *b1, b2;
      C() { b1 = b(); b2 = b();}
      bool *b() { if (rand() < 0.5) throw true; else return new b; }
      };

      int main()
      {
      C* c;
      try
      {
      c = new C();
      }
      catch (...)
      {
      // now, what might c point to? What might c->b1 or c->b2 point to?
      }
      return;
      }

      "Carl Daniel [VC++ MVP]" <cpdaniel_remov e_this_and_nosp am@mvps.org.nos pam>
      wrote in message news:%23j08xc%2 37DHA.2432@TK2M SFTNGP10.phx.gb l...[color=blue]
      > Bonj wrote:[color=green]
      > > OK I know a constructor can't have a return value but is it feasible
      > > such that I have a class whereby: //in MyClass1.h
      > > class MyClass1
      > > {
      > > MyClass1(){};
      > > ~MyClass1(){};
      > > MyClass1(int & Result) {Result = InitMyClass()};
      > >
      > > int InitMyClass();
      > > }
      > >
      > > //in main.cpp
      > >
      > > int main()
      > > {
      > > int result;
      > > MyClass theobject(resul t);
      > > printf("The result of initializing the class is %d", result);
      > > }[/color]
      >
      > Of course it's feasible, and perfectly legal.
      >
      > The Standard C++ way of indicating failure in a constructor is to throw an
      > exception, but there might be reasons sometimes that you don't want to do
      > that (the only one that comes to mind is a severe performance constraint -
      > exception throwing is expensive).
      >
      > -cd
      >
      >[/color]


      Comment

      • Carl Daniel [VC++ MVP]

        #4
        Re: Constructor return value?

        This situation should be handled by following the RAII principle: Resource
        Acquisition Is Initialization.

        struct C
        {
        boost::scoped_p tr<bool> b1, b2;
        C() : b1(b()), b2(b()) {}
        bool *b() { if (rand() < 0.5) throw true; else return new b; }
        };

        Now if an exception is thrown you're guaranteed that if b1 was initialized,
        it'll be destructed.

        -cd

        Simon Trew wrote:[color=blue]
        > There is another reason not to throw out of a constructor: you don't
        > know how well or badly the object is constructed, so you can't clean
        > up. This is most important if the constructor allocates resources
        > (e.g. memory) dynamically.
        >
        > e.g.
        >
        > struct C
        > {
        > bool *b1, b2;
        > C() { b1 = b(); b2 = b();}
        > bool *b() { if (rand() < 0.5) throw true; else return new b; }
        > };
        >
        > int main()
        > {
        > C* c;
        > try
        > {
        > c = new C();
        > }
        > catch (...)
        > {
        > // now, what might c point to? What might c->b1 or c->b2
        > point to? }
        > return;
        > }
        >
        > "Carl Daniel [VC++ MVP]"
        > <cpdaniel_remov e_this_and_nosp am@mvps.org.nos pam> wrote in message
        > news:%23j08xc%2 37DHA.2432@TK2M SFTNGP10.phx.gb l...[color=green]
        >> Bonj wrote:[color=darkred]
        >>> OK I know a constructor can't have a return value but is it feasible
        >>> such that I have a class whereby: //in MyClass1.h
        >>> class MyClass1
        >>> {
        >>> MyClass1(){};
        >>> ~MyClass1(){};
        >>> MyClass1(int & Result) {Result = InitMyClass()};
        >>>
        >>> int InitMyClass();
        >>> }
        >>>
        >>> //in main.cpp
        >>>
        >>> int main()
        >>> {
        >>> int result;
        >>> MyClass theobject(resul t);
        >>> printf("The result of initializing the class is %d", result);
        >>> }[/color]
        >>
        >> Of course it's feasible, and perfectly legal.
        >>
        >> The Standard C++ way of indicating failure in a constructor is to
        >> throw an exception, but there might be reasons sometimes that you
        >> don't want to do that (the only one that comes to mind is a severe
        >> performance constraint - exception throwing is expensive).
        >>
        >> -cd[/color][/color]


        Comment

        • Simon Trew

          #5
          Re: Constructor return value?

          Absolutely, but (unless I am thinking fuzzily as usual) that only moves it
          down a peg: we can only construct members that themselves obey the RAII
          principle. (If boost::scoped_p tr's constructor threw after allocating some
          resource then we'd be back to square one.)

          S.

          "Carl Daniel [VC++ MVP]" <cpdaniel_remov e_this_and_nosp am@mvps.org.nos pam>
          wrote in message news:OzfhZ%23J8 DHA.632@TK2MSFT NGP12.phx.gbl.. .[color=blue]
          > This situation should be handled by following the RAII principle:[/color]
          Resource[color=blue]
          > Acquisition Is Initialization.
          >
          > struct C
          > {
          > boost::scoped_p tr<bool> b1, b2;
          > C() : b1(b()), b2(b()) {}
          > bool *b() { if (rand() < 0.5) throw true; else return new b; }
          > };
          >
          > Now if an exception is thrown you're guaranteed that if b1 was[/color]
          initialized,[color=blue]
          > it'll be destructed.
          >
          > -cd
          >
          > Simon Trew wrote:[color=green]
          > > There is another reason not to throw out of a constructor: you don't
          > > know how well or badly the object is constructed, so you can't clean
          > > up. This is most important if the constructor allocates resources
          > > (e.g. memory) dynamically.
          > >
          > > e.g.
          > >
          > > struct C
          > > {
          > > bool *b1, b2;
          > > C() { b1 = b(); b2 = b();}
          > > bool *b() { if (rand() < 0.5) throw true; else return new b; }
          > > };
          > >
          > > int main()
          > > {
          > > C* c;
          > > try
          > > {
          > > c = new C();
          > > }
          > > catch (...)
          > > {
          > > // now, what might c point to? What might c->b1 or c->b2
          > > point to? }
          > > return;
          > > }
          > >
          > > "Carl Daniel [VC++ MVP]"
          > > <cpdaniel_remov e_this_and_nosp am@mvps.org.nos pam> wrote in message
          > > news:%23j08xc%2 37DHA.2432@TK2M SFTNGP10.phx.gb l...[color=darkred]
          > >> Bonj wrote:
          > >>> OK I know a constructor can't have a return value but is it feasible
          > >>> such that I have a class whereby: //in MyClass1.h
          > >>> class MyClass1
          > >>> {
          > >>> MyClass1(){};
          > >>> ~MyClass1(){};
          > >>> MyClass1(int & Result) {Result = InitMyClass()};
          > >>>
          > >>> int InitMyClass();
          > >>> }
          > >>>
          > >>> //in main.cpp
          > >>>
          > >>> int main()
          > >>> {
          > >>> int result;
          > >>> MyClass theobject(resul t);
          > >>> printf("The result of initializing the class is %d", result);
          > >>> }
          > >>
          > >> Of course it's feasible, and perfectly legal.
          > >>
          > >> The Standard C++ way of indicating failure in a constructor is to
          > >> throw an exception, but there might be reasons sometimes that you
          > >> don't want to do that (the only one that comes to mind is a severe
          > >> performance constraint - exception throwing is expensive).
          > >>
          > >> -cd[/color][/color]
          >
          >[/color]


          Comment

          • Carl Daniel [VC++ MVP]

            #6
            Re: Constructor return value?

            Simon Trew wrote:[color=blue]
            > Absolutely, but (unless I am thinking fuzzily as usual) that only
            > moves it down a peg: we can only construct members that themselves
            > obey the RAII principle. (If boost::scoped_p tr's constructor threw
            > after allocating some resource then we'd be back to square one.)[/color]

            Sure. But properly designed RAII containers (like boost::scoped_p tr) will
            behave correctly. In the example given, the only thing that can throw is
            the new expression, and if that throws boost::scoped_p tr's constructor will
            never be entered. If new doesn't throw and scoped_ptr's constructor is
            entered, it must either properly recover from any exception or (in reality)
            promise not to throw.

            -cd


            Comment

            • Doug Harrison [MVP]

              #7
              Re: Constructor return value?

              Simon Trew wrote:
              [color=blue]
              >Absolutely, but (unless I am thinking fuzzily as usual) that only moves it
              >down a peg: we can only construct members that themselves obey the RAII
              >principle.[/color]

              Well, yes, you gotta start somewhere. :) But once you have a set of nice,
              exception-safe, low-level classes such as std::string, std::vector, various
              smart pointers, etc, you can build your own classes in terms of them and not
              worry about them leaking.
              [color=blue]
              >(If boost::scoped_p tr's constructor threw after allocating some
              >resource then we'd be back to square one.)[/color]

              That's a problem only if you have a mix of exception-safe and unsafe
              members. I can't remember the last time I used a raw pointer as a class
              member, and that pointer owned the data it pointed to.

              --
              Doug Harrison
              Microsoft MVP - Visual C++

              Comment

              • Simon Trew

                #8
                Re: Constructor return value?

                Yep, I was not suggesting that boost::scoped_p tr behaved anything other than
                properly.

                "Carl Daniel [VC++ MVP]" <cpdaniel_remov e_this_and_nosp am@mvps.org.nos pam>
                wrote in message news:%23ug7PDM8 DHA.2952@TK2MSF TNGP09.phx.gbl. ..[color=blue]
                > Sure. But properly designed RAII containers (like boost::scoped_p tr) will
                > behave correctly.[/color]


                Comment

                Working...