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.
  • 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)

    A Offline
    A Offline
    Andy Brummer
    wrote on last edited by
    #15

    I think the init() concept ranks up there with initialization through property setters. X| Initialization in the constructor means that you can't have access to the object from outside code until the constructor completes unless you are doing something like an inplace new. Plus one of the biggest sources of C++ bugs is not calling delete, now you've just added this potential to stack allocated objects too. It's even worse for mutlithreaded code since you are just introducing the possibility of extra race conditions. So, I'd just require that every object with the init and clear methods implement 2 static methods:

    object* Construct()
    {
    object* obj = new object();
    obj->init();
    return obj;
    }

    void Destruct(object* obj)
    {
    obj->clear();
    delete obj;
    }

    Either that or add a init_ptr<> smart pointer class.


    This blanket smells like ham

    J 1 Reply Last reply
    0
    • P pbraun

      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. Having stated that, I firmly believe that all variables should be initialized before first use, unless the first use is to initialize them and therefore I still use the constructor to give the variables of the class an initial value as much as is reasonable. In doing this my code always has a known starting point.

      Phil

      P Offline
      P Offline
      Patrick Etc
      wrote on last edited by
      #16

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