Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. The Lounge
  3. another preference question....

another preference question....

Scheduled Pinned Locked Moved The Lounge
questionc++designcollaborationperformance
84 Posts 54 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Patrick Etc

    pbraun wrote:

    The main reason that separate methods are used for initialization and cleanup is for easier debugging purposes. There are too many times when a bug is found in the constructor or destructor after many painful hours of debugging. Using the separate methods allows one to isolate those points more easily.

    Ok. Make them separate methods and call them inside the constructor. Yes? I do this all the time. I prefer my objects to start with a known state than wonder if some method has been called yet.

    P Offline
    P Offline
    pbraun
    wrote on last edited by
    #19

    Patrick Sears wrote:

    call them inside the constructor

    There are very valid reasons to use them outside of the constructor as well. When one is developing the class, one needs to be clear as to the reasons why the constructor and destructors are separate.

    Phil

    E 1 Reply Last reply
    0
    • N Nemanja Trifunovic

      El Corazon wrote:

      Others have promoted an init()/configure() methodology and cleanup()/clear() so that constructors construct the class, not the content, init()/configure() sets up the content, cleanup()/clear() removes the content (which I have used for specific reusable storage type classes, but never as a hard rule of everything) and destructor pretty much does nothing unless memory allocation is involved.

      That idiom is called "two-phase construction" and was widely used before exceptions were available for C++. For instance, MFC uses it all the time simply because VC++ didn't support exceptions at the time that MFC was designed. In general, today most experts including Stroustrup recommend avoiding two-phase construction, but some people don't use exceptions for one reason or another and they really have little choice: constructors can't return values to tell us if something went wrong :)


      Programming Blog utf8-cpp

      E Offline
      E Offline
      El Corazon
      wrote on last edited by
      #20

      Nemanja Trifunovic wrote:

      and was widely used before exceptions were available for C++.

      the advantage of me learning from books later in the game. :laugh: Actually, that explains a lot. Thanks.

      _________________________ Asu no koto o ieba, tenjo de nezumi ga warau. Talk about things of tomorrow and the mice in the ceiling laugh. (Japanese Proverb)

      1 Reply Last reply
      0
      • E El Corazon

        Just curious. Had this disagreement with my team a while back and lost. I didn't want to bring it up then as it would be pointless. But I am curious on a design issue with classes. I was brought up (admittedly on books for C++, not college), that constructors not only construct, but initialize everything so that the class is "ready to be used" alternately the destructor removes everything and cleans up after itself. This way there is never an issue as far as timing when you use the contents of a class. Others have promoted an init()/configure() methodology and cleanup()/clear() so that constructors construct the class, not the content, init()/configure() sets up the content, cleanup()/clear() removes the content (which I have used for specific reusable storage type classes, but never as a hard rule of everything) and destructor pretty much does nothing unless memory allocation is involved. Of course this also means, if threads are involved there requires an additional start() after configure() to get the ball rolling which creats a set of "do this first directives" in the documentation. :~ I do freely admit no college training, not sure if this is a college thing or not. I am not a lover of absolutes, but I did always like my classes clean so that they start and stop by scope properly (everything handled by constructors and destructors), and now I find myself staring at my code as if it is growing green, black and white mold with the recent changes to it. X| Is this a college teaching method? Have I been putting too much effort into organizing my classes as independant entities?

        _________________________ Asu no koto o ieba, tenjo de nezumi ga warau. Talk about things of tomorrow and the mice in the ceiling laugh. (Japanese Proverb)

        M Offline
        M Offline
        Member 96
        wrote on last edited by
        #21

        I'm with you on this one, I really can't see the need for all those extra methods, it seems error prone and messy to me. Of course I didn't learn how to program in an ivory tower either. ;)


        "I don't want more choice. I just want better things!" - Edina Monsoon

        1 Reply Last reply
        0
        • D Dario Solera

          Leslie Sanford wrote:

          Instead, I must remember to call Dispose where it is implemented.

          Not really needed if the object does not consumes lots of memory... Dispose/Finalize is invoked automatically (but not necessarily immediately) when the instance goes out of scope.

          If you truly believe you need to pick a mobile phone that "says something" about your personality, don't bother. You don't have a personality. A mental illness, maybe - but not a personality. - Charlie Brooker My Blog - My Photos - ScrewTurn Wiki

          L Offline
          L Offline
          Leslie Sanford
          wrote on last edited by
          #22

          Dario Solera wrote:

          Dispose/Finalize is invoked automatically (but not necessarily immediately) when the instance goes out of scope.

          I don't think Dispose is invoked automatically. I know the finalizer is, but by the time it's invoked, you can't count on any of the references in your object as still being valid. They may have already been collected. You can release unmanaged resources (which is important), but that's about it.

          D D 2 Replies Last reply
          0
          • E El Corazon

            Just curious. Had this disagreement with my team a while back and lost. I didn't want to bring it up then as it would be pointless. But I am curious on a design issue with classes. I was brought up (admittedly on books for C++, not college), that constructors not only construct, but initialize everything so that the class is "ready to be used" alternately the destructor removes everything and cleans up after itself. This way there is never an issue as far as timing when you use the contents of a class. Others have promoted an init()/configure() methodology and cleanup()/clear() so that constructors construct the class, not the content, init()/configure() sets up the content, cleanup()/clear() removes the content (which I have used for specific reusable storage type classes, but never as a hard rule of everything) and destructor pretty much does nothing unless memory allocation is involved. Of course this also means, if threads are involved there requires an additional start() after configure() to get the ball rolling which creats a set of "do this first directives" in the documentation. :~ I do freely admit no college training, not sure if this is a college thing or not. I am not a lover of absolutes, but I did always like my classes clean so that they start and stop by scope properly (everything handled by constructors and destructors), and now I find myself staring at my code as if it is growing green, black and white mold with the recent changes to it. X| Is this a college teaching method? Have I been putting too much effort into organizing my classes as independant entities?

            _________________________ Asu no koto o ieba, tenjo de nezumi ga warau. Talk about things of tomorrow and the mice in the ceiling laugh. (Japanese Proverb)

            P Offline
            P Offline
            Paul Watson
            wrote on last edited by
            #23

            I'm sure we can invent reasons to do it their way but in everyday coding at a business logic level I really do think an instance should be initialised to a common state on construction. Code runs in all manner of environments and they are not all equal. Rather have your code set the playing field than the environment.

            regards, Paul Watson Ireland & South Africa

            Shog9 wrote:

            And with that, Paul closed his browser, sipped his herbal tea, fixed the flower in his hair, and smiled brightly at the multitude of cute, furry animals flocking around the grassy hillside where he sat coding Ruby on his Mac...

            1 Reply Last reply
            0
            • L Leslie Sanford

              Dario Solera wrote:

              Dispose/Finalize is invoked automatically (but not necessarily immediately) when the instance goes out of scope.

              I don't think Dispose is invoked automatically. I know the finalizer is, but by the time it's invoked, you can't count on any of the references in your object as still being valid. They may have already been collected. You can release unmanaged resources (which is important), but that's about it.

              D Offline
              D Offline
              Dario Solera
              wrote on last edited by
              #24

              Leslie Sanford wrote:

              I don't think Dispose is invoked automatically. I know the finalizer is, but by the time it's invoked, you can't count on any of the references in your object as still being valid. They may have already been collected. You can release unmanaged resources (which is important), but that's about it.

              You're right. Finalize is invoked non-deterministically, but Dispose must be called explicitly. My fault. :-O

              If you truly believe you need to pick a mobile phone that "says something" about your personality, don't bother. You don't have a personality. A mental illness, maybe - but not a personality. - Charlie Brooker My Blog - My Photos - ScrewTurn Wiki

              1 Reply Last reply
              0
              • N Nemanja Trifunovic

                El Corazon wrote:

                Others have promoted an init()/configure() methodology and cleanup()/clear() so that constructors construct the class, not the content, init()/configure() sets up the content, cleanup()/clear() removes the content (which I have used for specific reusable storage type classes, but never as a hard rule of everything) and destructor pretty much does nothing unless memory allocation is involved.

                That idiom is called "two-phase construction" and was widely used before exceptions were available for C++. For instance, MFC uses it all the time simply because VC++ didn't support exceptions at the time that MFC was designed. In general, today most experts including Stroustrup recommend avoiding two-phase construction, but some people don't use exceptions for one reason or another and they really have little choice: constructors can't return values to tell us if something went wrong :)


                Programming Blog utf8-cpp

                M Offline
                M Offline
                Miszou
                wrote on last edited by
                #25

                Nemanja Trifunovic wrote:

                constructors can't return values to tell us if something went wrong

                I've recently started using a library that makes all constructors inaccessible, and all objects must be created by a overloads of a static Create method on the object. eg:

                class MyClass
                {
                    private MyClass() {}
                
                    public static MyClass Create()
                    {
                        return new MyClass();
                    }
                }
                

                I first thought that this was because constructors could not return failure codes, but as I type this, I realize that a static Create method with a specific return type can't return a status code either! Then I thought it was for serializing the object or something of that nature, but with reflection (in .NET), you can call a constructor as easily as any other method. My final thoughts on this, are that the Create method does not have to return a specific instance, while a constructor does. This means that in a complex hierarchy, you can be given a descendent object instead of the object you asked actually asked for, depending on how the Create method works. A highly contrived example:

                class ClassA
                {
                    private ClassA() {}
                
                    public static ClassA Create( int x )
                    {
                        if ( x < 0 )
                            return new ClassA();
                        else
                            return ClassB.Create();
                    }
                }
                
                class ClassB : ClassA
                {
                    private ClassB() {}
                
                    public static ClassB()
                    {
                        return new ClassB();
                    }
                }
                
                static void main()
                {
                    ClassA myClass = ClassA.Create( 3 ); // Will really create a ClassB
                }
                

                Is this what it's used for? Or am I heading into La-La Land with this line of thinking?


                Sunrise Wallpaper Project | The StartPage Randomizer | A Random Web Page

                D D 2 Replies Last reply
                0
                • P pbraun

                  Patrick Sears wrote:

                  call them inside the constructor

                  There are very valid reasons to use them outside of the constructor as well. When one is developing the class, one needs to be clear as to the reasons why the constructor and destructors are separate.

                  Phil

                  E Offline
                  E Offline
                  ewasjdgb
                  wrote on last edited by
                  #26

                  pbraun wrote:

                  There are very valid reasons to use them outside of the constructor as well

                  I think the term 'as well' qualifies it really. IMHO it's fine to call the init() outside of the constructor as well, but seems foolish to not to call it at construct time - even if all it does is initialise the object to a NULL state.

                  B P 2 Replies Last reply
                  0
                  • E El Corazon

                    Just curious. Had this disagreement with my team a while back and lost. I didn't want to bring it up then as it would be pointless. But I am curious on a design issue with classes. I was brought up (admittedly on books for C++, not college), that constructors not only construct, but initialize everything so that the class is "ready to be used" alternately the destructor removes everything and cleans up after itself. This way there is never an issue as far as timing when you use the contents of a class. Others have promoted an init()/configure() methodology and cleanup()/clear() so that constructors construct the class, not the content, init()/configure() sets up the content, cleanup()/clear() removes the content (which I have used for specific reusable storage type classes, but never as a hard rule of everything) and destructor pretty much does nothing unless memory allocation is involved. Of course this also means, if threads are involved there requires an additional start() after configure() to get the ball rolling which creats a set of "do this first directives" in the documentation. :~ I do freely admit no college training, not sure if this is a college thing or not. I am not a lover of absolutes, but I did always like my classes clean so that they start and stop by scope properly (everything handled by constructors and destructors), and now I find myself staring at my code as if it is growing green, black and white mold with the recent changes to it. X| Is this a college teaching method? Have I been putting too much effort into organizing my classes as independant entities?

                    _________________________ Asu no koto o ieba, tenjo de nezumi ga warau. Talk about things of tomorrow and the mice in the ceiling laugh. (Japanese Proverb)

                    R Offline
                    R Offline
                    Rama Krishna Vavilala
                    wrote on last edited by
                    #27

                    I think it depends. Normally I would lean towards the constructor based initialization but not always. In the end you have to decide whether it improves code readability. Here is an horror story which ought to go to the Coding Horrors. In my previous company, I was fixing an issue and in that file I found the following code:

                    void PostInvoice()
                    {
                    ApbhTivhStatusChange * pChg = new ApbhTivhStatusChange(m_pContext);
                    delete pChg;

                    //Some other code follows this is where the real bug I was
                    //supposed to fix was
                    }

                    After fixing the issue, I removed the first 3 lines of the function thinking that it was not doing anything as the process function was commented out. My bug fix worked correctly and I checked it in. I modified like this:

                    void PostInvoice()
                    {
                    //Some other code follows this is where the real bug I was
                    //supposed to fix was
                    }

                    Later on is QA testing it was discovered that seem other piece of application functionality broke. It was embarrassing to find that the code I removed caused the issue. It was not a big issue to discover that the work was being done in the constructor and destructor of ApbhTivhStatusChange class.

                    class ApbhTivhStatusChange
                    {
                    private:
                    Context* m_pContext;

                    public:
                    ApbhTivhStatusChange(Context* pContext)
                    {
                    pContext->ConnectToDatabase();
                    pContext->BalanceInvoice();
                    }

                    ~ApbhTivhStatusChange()
                    {
                    pContext->Cleanup();
                    }
                    }

                    The above code was poorly written even though it worked. It caused a huge confusion. But one thing is for sure, you should always add clean up code in the destructor. There are very few cases where I found that it is not advisable to do so and of course you need to make sure that the destructors do not throw any exceptions but at the same time they log the exceptions.

                    Co-Author ASP.NET AJAX in Action

                    B 1 Reply Last reply
                    0
                    • E El Corazon

                      Just curious. Had this disagreement with my team a while back and lost. I didn't want to bring it up then as it would be pointless. But I am curious on a design issue with classes. I was brought up (admittedly on books for C++, not college), that constructors not only construct, but initialize everything so that the class is "ready to be used" alternately the destructor removes everything and cleans up after itself. This way there is never an issue as far as timing when you use the contents of a class. Others have promoted an init()/configure() methodology and cleanup()/clear() so that constructors construct the class, not the content, init()/configure() sets up the content, cleanup()/clear() removes the content (which I have used for specific reusable storage type classes, but never as a hard rule of everything) and destructor pretty much does nothing unless memory allocation is involved. Of course this also means, if threads are involved there requires an additional start() after configure() to get the ball rolling which creats a set of "do this first directives" in the documentation. :~ I do freely admit no college training, not sure if this is a college thing or not. I am not a lover of absolutes, but I did always like my classes clean so that they start and stop by scope properly (everything handled by constructors and destructors), and now I find myself staring at my code as if it is growing green, black and white mold with the recent changes to it. X| Is this a college teaching method? Have I been putting too much effort into organizing my classes as independant entities?

                      _________________________ Asu no koto o ieba, tenjo de nezumi ga warau. Talk about things of tomorrow and the mice in the ceiling laugh. (Japanese Proverb)

                      P Offline
                      P Offline
                      Phil Harding
                      wrote on last edited by
                      #28

                      El Corazon wrote:

                      Others have promoted an init()/configure() methodology and cleanup()/clear() so that constructors construct the class, not the content, init()/configure() sets up the content, cleanup()/clear() removes the content

                      I find that argument totally bogus, the new operator creates an object instance, and then runs the constructor "over" that instance, the contructor is nothing more than a function which is automatically run when a new object instance is created, a constrructors raison d'etre is to initialise the object instance ready for use. By that score the constructor is badly named, it should have been called the initialiser :^)


                      - "I'm not lying, I'm just writing fiction with my mouth"

                      Phil Harding.
                      myBlog [^] | mySite [^]

                      1 Reply Last reply
                      0
                      • E El Corazon

                        Just curious. Had this disagreement with my team a while back and lost. I didn't want to bring it up then as it would be pointless. But I am curious on a design issue with classes. I was brought up (admittedly on books for C++, not college), that constructors not only construct, but initialize everything so that the class is "ready to be used" alternately the destructor removes everything and cleans up after itself. This way there is never an issue as far as timing when you use the contents of a class. Others have promoted an init()/configure() methodology and cleanup()/clear() so that constructors construct the class, not the content, init()/configure() sets up the content, cleanup()/clear() removes the content (which I have used for specific reusable storage type classes, but never as a hard rule of everything) and destructor pretty much does nothing unless memory allocation is involved. Of course this also means, if threads are involved there requires an additional start() after configure() to get the ball rolling which creats a set of "do this first directives" in the documentation. :~ I do freely admit no college training, not sure if this is a college thing or not. I am not a lover of absolutes, but I did always like my classes clean so that they start and stop by scope properly (everything handled by constructors and destructors), and now I find myself staring at my code as if it is growing green, black and white mold with the recent changes to it. X| Is this a college teaching method? Have I been putting too much effort into organizing my classes as independant entities?

                        _________________________ Asu no koto o ieba, tenjo de nezumi ga warau. Talk about things of tomorrow and the mice in the ceiling laugh. (Japanese Proverb)

                        J Offline
                        J Offline
                        Janzen
                        wrote on last edited by
                        #29

                        If you want to bring it up with the team again, and I would personally, the name of the pattern that you use is called Resource Acquisition Is Initialization. The best reason for using this pattern, in my opinion, is that it is exception safe. If an exception happens it the object will be cleaned up automatically when the destructor is called, without you having to specifically needing to call the cleanup method. A quick google search for RAII will bring up plenty of reasons to discuss with your team should you ever find yourself in that argument again.

                        N J 2 Replies Last reply
                        0
                        • E El Corazon

                          Just curious. Had this disagreement with my team a while back and lost. I didn't want to bring it up then as it would be pointless. But I am curious on a design issue with classes. I was brought up (admittedly on books for C++, not college), that constructors not only construct, but initialize everything so that the class is "ready to be used" alternately the destructor removes everything and cleans up after itself. This way there is never an issue as far as timing when you use the contents of a class. Others have promoted an init()/configure() methodology and cleanup()/clear() so that constructors construct the class, not the content, init()/configure() sets up the content, cleanup()/clear() removes the content (which I have used for specific reusable storage type classes, but never as a hard rule of everything) and destructor pretty much does nothing unless memory allocation is involved. Of course this also means, if threads are involved there requires an additional start() after configure() to get the ball rolling which creats a set of "do this first directives" in the documentation. :~ I do freely admit no college training, not sure if this is a college thing or not. I am not a lover of absolutes, but I did always like my classes clean so that they start and stop by scope properly (everything handled by constructors and destructors), and now I find myself staring at my code as if it is growing green, black and white mold with the recent changes to it. X| Is this a college teaching method? Have I been putting too much effort into organizing my classes as independant entities?

                          _________________________ Asu no koto o ieba, tenjo de nezumi ga warau. Talk about things of tomorrow and the mice in the ceiling laugh. (Japanese Proverb)

                          B Offline
                          B Offline
                          Bijesh
                          wrote on last edited by
                          #30

                          Just to add on to what others have said, even with exceptions, in C++, an exception raised inside a constructor still poses a problem. For example, if you are using a pointer, and the constructor thew an exception, do you delete the object through that pointer? Is it needed/safe? It was safer to do just simple initialisations within the constructor, and put anything that can go wrong in a separate method.

                          R N J 3 Replies Last reply
                          0
                          • B Bijesh

                            Just to add on to what others have said, even with exceptions, in C++, an exception raised inside a constructor still poses a problem. For example, if you are using a pointer, and the constructor thew an exception, do you delete the object through that pointer? Is it needed/safe? It was safer to do just simple initialisations within the constructor, and put anything that can go wrong in a separate method.

                            R Offline
                            R Offline
                            Rama Krishna Vavilala
                            wrote on last edited by
                            #31

                            Bijesh wrote:

                            For example, if you are using a pointer, and the constructor thew an exception, do you delete the object through that pointer?

                            The object automatically gets deleted if the construtcor throws an exception and the VC++ compiler implements this feature correctly. That's is the reason why if you create a placement form of new operator you also need to create a matching placement form of delete operator.

                            Co-Author ASP.NET AJAX in Action

                            1 Reply Last reply
                            0
                            • B Bijesh

                              Just to add on to what others have said, even with exceptions, in C++, an exception raised inside a constructor still poses a problem. For example, if you are using a pointer, and the constructor thew an exception, do you delete the object through that pointer? Is it needed/safe? It was safer to do just simple initialisations within the constructor, and put anything that can go wrong in a separate method.

                              N Offline
                              N Offline
                              Nemanja Trifunovic
                              wrote on last edited by
                              #32

                              Bijesh wrote:

                              For example, if you are using a pointer, and the constructor thew an exception, do you delete the object through that pointer? Is it needed/safe?

                              That's why raw pointers are a bad idea. Use RAII[^] and life will be good :)


                              Programming Blog utf8-cpp

                              1 Reply Last reply
                              0
                              • J Janzen

                                If you want to bring it up with the team again, and I would personally, the name of the pattern that you use is called Resource Acquisition Is Initialization. The best reason for using this pattern, in my opinion, is that it is exception safe. If an exception happens it the object will be cleaned up automatically when the destructor is called, without you having to specifically needing to call the cleanup method. A quick google search for RAII will bring up plenty of reasons to discuss with your team should you ever find yourself in that argument again.

                                N Offline
                                N Offline
                                Nemanja Trifunovic
                                wrote on last edited by
                                #33

                                Janzen wrote:

                                the name of the pattern that you use is called Resource Acquisition Is Initialization.

                                Amen. Although it is surprising how many people refuse to grasp it.


                                Programming Blog utf8-cpp

                                1 Reply Last reply
                                0
                                • R Rama Krishna Vavilala

                                  I think it depends. Normally I would lean towards the constructor based initialization but not always. In the end you have to decide whether it improves code readability. Here is an horror story which ought to go to the Coding Horrors. In my previous company, I was fixing an issue and in that file I found the following code:

                                  void PostInvoice()
                                  {
                                  ApbhTivhStatusChange * pChg = new ApbhTivhStatusChange(m_pContext);
                                  delete pChg;

                                  //Some other code follows this is where the real bug I was
                                  //supposed to fix was
                                  }

                                  After fixing the issue, I removed the first 3 lines of the function thinking that it was not doing anything as the process function was commented out. My bug fix worked correctly and I checked it in. I modified like this:

                                  void PostInvoice()
                                  {
                                  //Some other code follows this is where the real bug I was
                                  //supposed to fix was
                                  }

                                  Later on is QA testing it was discovered that seem other piece of application functionality broke. It was embarrassing to find that the code I removed caused the issue. It was not a big issue to discover that the work was being done in the constructor and destructor of ApbhTivhStatusChange class.

                                  class ApbhTivhStatusChange
                                  {
                                  private:
                                  Context* m_pContext;

                                  public:
                                  ApbhTivhStatusChange(Context* pContext)
                                  {
                                  pContext->ConnectToDatabase();
                                  pContext->BalanceInvoice();
                                  }

                                  ~ApbhTivhStatusChange()
                                  {
                                  pContext->Cleanup();
                                  }
                                  }

                                  The above code was poorly written even though it worked. It caused a huge confusion. But one thing is for sure, you should always add clean up code in the destructor. There are very few cases where I found that it is not advisable to do so and of course you need to make sure that the destructors do not throw any exceptions but at the same time they log the exceptions.

                                  Co-Author ASP.NET AJAX in Action

                                  B Offline
                                  B Offline
                                  Big Daddy Farang
                                  wrote on last edited by
                                  #34

                                  Whoever wrote the original PostInvoice() and did not comment the purpose of the first two lines should be taken out and shot. BDF

                                  R 1 Reply Last reply
                                  0
                                  • B Big Daddy Farang

                                    Whoever wrote the original PostInvoice() and did not comment the purpose of the first two lines should be taken out and shot. BDF

                                    R Offline
                                    R Offline
                                    Rama Krishna Vavilala
                                    wrote on last edited by
                                    #35

                                    The code actually evolved passing through several developers, the original developer might have done it correctly. It was probably the idea of a later developer who was a newbie to use the constructor an destructor to do all the work.

                                    Co-Author ASP.NET AJAX in Action

                                    E 1 Reply Last reply
                                    0
                                    • R Rama Krishna Vavilala

                                      The code actually evolved passing through several developers, the original developer might have done it correctly. It was probably the idea of a later developer who was a newbie to use the constructor an destructor to do all the work.

                                      Co-Author ASP.NET AJAX in Action

                                      E Offline
                                      E Offline
                                      El Corazon
                                      wrote on last edited by
                                      #36

                                      Rama Krishna Vavilala wrote:

                                      The code actually evolved passing through several developers, the original developer might have done it correctly. It was probably the idea of a later developer who was a newbie to use the constructor an destructor to do all the work.

                                      we had something like that happen to us. It was in an Ascii to Latitude/Longitude routine. I forget the name of the method, but it supported several types of latitude or longitude references (dd.decimal or dd mm.dec or dd mm ss.dec). Another programmer got ahold of the method and continued addition additional inputs beyond even latitude and longitude, attempting the equivalent generalality of a scanf() for geodetic values. Pass about 6 months and no one knew these changes occured and everything was still going fine, until we tried to run a specific data set in a specific format, and intermittent jumps were occuring in the data. Turns out the new changes were not thread-safe, and the routine had grown so complex supporting so many types that it was a pain to track down! mind you, the method was still directly referenced as something to the extent of ascii 2 latlong in the name, so everyone thought it still did just that.

                                      _________________________ Asu no koto o ieba, tenjo de nezumi ga warau. Talk about things of tomorrow and the mice in the ceiling laugh. (Japanese Proverb)

                                      1 Reply Last reply
                                      0
                                      • M Miszou

                                        Nemanja Trifunovic wrote:

                                        constructors can't return values to tell us if something went wrong

                                        I've recently started using a library that makes all constructors inaccessible, and all objects must be created by a overloads of a static Create method on the object. eg:

                                        class MyClass
                                        {
                                            private MyClass() {}
                                        
                                            public static MyClass Create()
                                            {
                                                return new MyClass();
                                            }
                                        }
                                        

                                        I first thought that this was because constructors could not return failure codes, but as I type this, I realize that a static Create method with a specific return type can't return a status code either! Then I thought it was for serializing the object or something of that nature, but with reflection (in .NET), you can call a constructor as easily as any other method. My final thoughts on this, are that the Create method does not have to return a specific instance, while a constructor does. This means that in a complex hierarchy, you can be given a descendent object instead of the object you asked actually asked for, depending on how the Create method works. A highly contrived example:

                                        class ClassA
                                        {
                                            private ClassA() {}
                                        
                                            public static ClassA Create( int x )
                                            {
                                                if ( x < 0 )
                                                    return new ClassA();
                                                else
                                                    return ClassB.Create();
                                            }
                                        }
                                        
                                        class ClassB : ClassA
                                        {
                                            private ClassB() {}
                                        
                                            public static ClassB()
                                            {
                                                return new ClassB();
                                            }
                                        }
                                        
                                        static void main()
                                        {
                                            ClassA myClass = ClassA.Create( 3 ); // Will really create a ClassB
                                        }
                                        

                                        Is this what it's used for? Or am I heading into La-La Land with this line of thinking?


                                        Sunrise Wallpaper Project | The StartPage Randomizer | A Random Web Page

                                        D Offline
                                        D Offline
                                        DavidNohejl
                                        wrote on last edited by
                                        #37

                                        http://en.wikipedia.org/wiki/Factory_method_pattern[^]


                                        [My Blog]
                                        "Visual studio desperately needs some performance improvements. It is sometimes almost as slow as eclipse." - Rüdiger Klaehn
                                        "Real men use mspaint for writing code and notepad for designing graphics." - Anna-Jayne Metcalfe

                                        1 Reply Last reply
                                        0
                                        • B Bijesh

                                          Just to add on to what others have said, even with exceptions, in C++, an exception raised inside a constructor still poses a problem. For example, if you are using a pointer, and the constructor thew an exception, do you delete the object through that pointer? Is it needed/safe? It was safer to do just simple initialisations within the constructor, and put anything that can go wrong in a separate method.

                                          J Offline
                                          J Offline
                                          James R Twine
                                          wrote on last edited by
                                          #38

                                          Bijesh wrote:

                                          For example, if you are using a pointer, and the constructor thew an exception, do you delete the object through that pointer?

                                          If the object was allocated using the non-placement (i.e. normal) version of new, the object is supposed to be "undone".  However (last checked on VC++ 6.0), members of that object will only be cleaned up if they themselves were fully constructed at the time of the exception, so the object is destructed (as best it could be), new returns NULL, so there is nothing to call delete on.    If the object was allocated on the stack, that stack context will be destroyed by the stack unwinding that takes place, so again there is nothing to manually destroy/cleanup.    Things change when you are dealing with placement new because you are basically directly calling the constructor to construct an object in a pre-allocated block of memory.  What you do in that case depends on what you are using the block of memory for.  You may free the entire block, or simply log the exception and continue with the next object reusing that block of memory.  You just have to watch out for that exception so that you do not end up using that "partially constructed" object (which I have done before :doh: - that is why I know it is possible, and know that the vtbl is/was the last thing to get initialized during construction).    Not many developers need to implement their own fixed-size-block-allocator-based object cache, or otherwise deal with placement new, so issues with throwing exceptions from constructors is a non-issue for many.    Peace!

                                          -=- James
                                          Please rate this message - let me know if I helped or not! * * * If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong!
                                          Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road!
                                          See DeleteFXPFiles

                                          B 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups