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 0 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.
  • L Leslie Sanford

    El Corazon wrote:

    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.

    I agree. Otherwise, what's the point of having constructors/destructors? I would find it strange if I'm using an API in which I have to call "Initialize" on an object before I can use it. Regarding destructors, I program mainly with C# now, and I miss the deterministic and automatic destruction mechanism of C++. Instead, I must remember to call Dispose where it is implemented. It seems rather procedural rather than object oriented to have to remember to call "Initialize/Cleanup" on objects rather than letting the constructor/destructor handle that for you. Having said that, sometimes it's necessary to establish the relationships between objects after they've been created. This is particularly true when you must have a parameterless constructor for whatever reason. Once an object is created, you can then establish its relationship with other objects by using its setters to set its properties. However, even in those situations, it's helpful if the object behaves normally regardless of whether any of its properties have been set. The "Null Object" design pattern can be helpful here.

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

    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 1 Reply Last reply
    0
    • J Jorgen Sigvardsson

      IMO, it boils down to this: 1) If the object is a first class entity - i.e., not a handle - then do initialization and finalization in constructor and destructor 2) If the object is a simple handle (such as a CWnd derivative), then there are two life lines - the handle object itself and whatever it's handling. Then I use init()/cleanup() to handle the life line of the handled object. My reason for 2) is that the destruction of handled object may fail - something I don't want to deal with in a destructor (if you say exception, then you've not only shot yourself in the foot, but you've also blown your brains out). Also, I might want to be able to share the handled object between handles, or I might just want to transfer the responsibility of it elsewhere. Note that this isn't something I've learned in school. I've picked it up as I go... :)

      -- Raaaaaaaaaaaaaaaaaaaaa!

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

      Joergen Sigvardsson wrote:

      IMO, it boils down to this: 1) If the object is a first class entity - i.e., not a handle - then do initialization and finalization in constructor and destructor 2) If the object is a simple handle (such as a CWnd derivative), then there are two life lines - the handle object itself and whatever it's handling. Then I use init()/cleanup() to handle the life line of the handled object. My reason for 2) is that the destruction of handled object may fail - something I don't want to deal with in a destructor (if you say exception, then you've not only shot yourself in the foot, but you've also blown your brains out). Also, I might want to be able to share the handled object between handles, or I might just want to transfer the responsibility of it elsewhere. Note that this isn't something I've learned in school. I've picked it up as I go...

      Hmm, interesting viewpoint. As someone who's written a lot of "wrapper" classes, I find your approach interesting. I'll have to give it some thought.

      1 Reply Last reply
      0
      • 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
                                          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