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

    led mike wrote:

    Well there is nothing wrong with breaking that out like that as long as they are then called from constructors,destructors, assignment operators etc.

    nope, called from outside.... myclass = new aclass(...); myclass->init(); myclass->start(); // if threads myclass->stop(); // if threads myclass->clear(); delete(myclass);

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

    H Offline
    H Offline
    Howard Richards
    wrote on last edited by
    #65

    As Mrs Thatcher once said.. "No No No!"[^] If Init() is something that should always be performed on a class before being used then it should be part of/called by the constructor. It should only be called/callable by the outside 'user' if it's optional. What happens if the user forgets to call init? or clear? Why make them remember when you can encapsulate that behaviour. This is why we have encapsulation..! As for clear, same principle applies, or use IDisposable if required.

    'Howard

    1 Reply Last reply
    0
    • J James R Twine

      Bijesh wrote:

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

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

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

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

      Very interesting info! Thanks.. Bijesh

      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)

        V Offline
        V Offline
        Vishal Doshi
        wrote on last edited by
        #67

        I've found that using only constructors is the most recommended appraoch (RAII - Resource Acquisition is Initialization). However, there are cases when you need Init() for instance if you want to construct some bits in one thread and some bits in another thread. Another example is a File object. File->Open() is really the init operation. The file object could be created with no attached file... The solutions I've used are: 1) Try as far as possible to always initialize fully in the constructor 2) When it is not possible -> Create a factory. For example: class FileFactory { FileFactory(string sDirectory); File CreateFile(string Filename) } which allows you to ensure that File objects are always fully initialised. 3) When neither approach is possible - or you create a FactoryFactoryFactory :) - create an Init() method - but then make sure that all class methods "check" that the object is in the correc state and throw if not. This makes the classes brittle - but - means that people forgetting to call Init() will atleast generate meaningfull error messages. -Vishal

        1 Reply Last reply
        0
        • L led mike

          Well there is nothing wrong with breaking that out like that as long as they are then called from constructors,destructors, assignment operators etc.

          A Offline
          A Offline
          Anna Jayne Metcalfe
          wrote on last edited by
          #68

          led mike wrote:

          Well there is nothing wrong with breaking that out like that as long as they are then called from constructors,destructors, assignment operators etc.

          One thing to be aware of is that doing so causes double initialisation (the default initialiser, then the init() called from the constructor. The only way to prevent that is to initialise class data in the constructor's initialiser list. Other than that, I've no issue with this approach except where someone then makes their init() and clear() virtual and calls them from constructors/destructor. This is such a bad idea in C++ it should cause a syntax error. X|

          Anna :rose: Linting the day away :cool: Anna's Place | Tears and Laughter "If mushy peas are the food of the devil, the stotty cake is the frisbee of God"

          L 1 Reply Last reply
          0
          • J Johann Gerell

            I like.

            -- Time you enjoy wasting is not wasted time - Bertrand Russel

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

            I hope that was humor, because my post definitely was.


            This blanket smells like ham

            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)

              _ Offline
              _ Offline
              __Nick
              wrote on last edited by
              #70

              My .02. Having an init function that is required to be called outside of the constructor is only useful in three situations 1 - When you have multiple constructors that all perform a set of common steps in addition to the custom steps that require different constructors. Moving the common steps to an init() function and calling it from the constructor makes for more modular code. 2 - When you are designing a class at the base of a class hierarchy that will need custom initialization before it can be used. Making init virtual and _NOT_ calling it from the constructor will perform the custom initialization. (Calling init from the base class in a constructor is BASE::init and not DERIVED::init). This can usually be done in a different manner. 3 - The class manages an expensive resource (or requires additional function calls to set parameters - username/password), and can't/shouldn't be ready for use on initialization. Usually the expensive resource scenario involves not a call to init(), but a call to open() or something similar. The username/password is similar, but I've seen always open socket designs that require authentication, but in those cases the init took the credentials. Regardless of what any book says I think that calling Some_Type * c = new SomeType(); c->init(); // Use some type here c->cleanup(); delete c; Is unnecessary, creates more of an opportunity to screw up, and ultimately just involves a wasted function call. In general if you have two steps that should always follow each other with nothing in between, they should be encapsulated to make sure that you always do so. Not doing so does not add any appreciable benefit. Debugging should be easier b/c everything is properly initialized, rather than it being seperated out.

              1 Reply Last reply
              0
              • P peterchen

                Very good criterion to separate these. HOWEVER, (muhahahah!)

                Joergen Sigvardsson wrote:

                the destruction of handled object may fail - something I don't want to deal with in a destructor

                however, if the caller doesn't call Close() - because he's lazy or an exception got into the way, you still have to deal with that.

                Joergen Sigvardsson wrote:

                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.

                But Joergen! That's why there is shared_ptr!


                We are a big screwed up dysfunctional psychotic happy family - some more screwed up, others more happy, but everybody's psychotic joint venture definition of CP
                My first real C# project | Linkify!|FoldWithUs! | sighist

                B Offline
                B Offline
                Big Endian 1
                wrote on last edited by
                #71

                All class members must be initialized in the constructor initialization list. This is a C++ best practice. Don't count on the user to do stuff for you, your class must be self initialized to eliminate unexpected behaviours. As for destructors, there is nothing wrong by making a private cleanup method and calling within the destructor.

                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)

                  S Offline
                  S Offline
                  SecondBreakfast
                  wrote on last edited by
                  #72

                  I got in the habit of doing very little in constructors in C++ because they don't have a return value and it was difficult to know if an error occurred during the initialization process. But, this was back when exceptions only existed in the MFC library as primitive "set/jump" implementation (no clean up). In those days it made more sense to just initialize member varialbes and use a seperate init() method to do any heavy lifting. Then if something failed, the init() could return some meaningful information and the caller could do something intelligent. However, now with structured exception handling, garbage collection, etc, it's makes more sense to do the work in the constructor in most cases. Nevertheless, I'd still argue that it's not bad design to limit the constructor to simple variable initialization and seperate out more complex initialization operations to another step in some situations. I know, what situations? Any situation where you don't want to handle an error condition by simply throwing a exception to the caller.

                  1 Reply Last reply
                  0
                  • A Anna Jayne Metcalfe

                    led mike wrote:

                    Well there is nothing wrong with breaking that out like that as long as they are then called from constructors,destructors, assignment operators etc.

                    One thing to be aware of is that doing so causes double initialisation (the default initialiser, then the init() called from the constructor. The only way to prevent that is to initialise class data in the constructor's initialiser list. Other than that, I've no issue with this approach except where someone then makes their init() and clear() virtual and calls them from constructors/destructor. This is such a bad idea in C++ it should cause a syntax error. X|

                    Anna :rose: Linting the day away :cool: Anna's Place | Tears and Laughter "If mushy peas are the food of the devil, the stotty cake is the frisbee of God"

                    L Offline
                    L Offline
                    led mike
                    wrote on last edited by
                    #73

                    Anna-Jayne Metcalfe wrote:

                    the default initialiser

                    Not sure what you mean?

                    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)

                      C Offline
                      C Offline
                      CBJG
                      wrote on last edited by
                      #74

                      Unless there is a compelling reason for using an init() function, it is really a waste of time and bad coding practice. However, there are instances where it is needed, or is much simpler to use an init() function. I do real-time, embedded programming and most of the classes have init() functions. The reason is that memory is statically allocated and fixed and initializing classes via constructors does not guarantee what order the classes are initialized in. Therefore, if a class depends on another class being set up already, for example (there are other reasons as well), the init() functions can be called after all the necessary set up is done. This guarantees that it is known precisely when the classes start running.

                      1 Reply Last reply
                      0
                      • O objarni

                        Leslie Sanford wrote:

                        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.

                        A little of topic, but I thought it was worth mentioning; Well -- Dispose() will be called by the garbage collector in any case -- so you don't really need to call it, unless you REALLY want to control the timing of the cleaning up of you resource. If I have such a scarce resource, say a database connection, that I really want to be cleaned up right now and not "in a couple of seconds", I use the C# keyword "using" this way: using(DatabaseConnection conn = DatabaseConnection.CreateInstance()) { ... } .. which automatically calls the Dispose() method of conn when exiting the code block {...} . Note that using() requires the declared object (conn here) to implement the IDisposable() interface. Even if I skipped the using() clause, conn.Dispose() would have been called when the garbage collector "thrashed" the conn some seconds later: DatabaseConnection conn = DatabaseConnection.CreateInstance(); ...

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

                        objarni wrote:

                        Well -- Dispose() will be called by the garbage collector in any case -- so you don't really need to call it, unless you REALLY want to control the timing of the cleaning up of you resource.

                        Clearly I need to brush up on my .NET knowledge. I was under the impression that you must call Dispose yourself. Here's the pattern I've learned from .NET documentation, at least when the class that implements IDisposable can be used as a base class:

                        public class SomeClass : IDisposable
                        {
                        ~SomeClass()
                        {
                        Dispose(false);
                        }

                        protected virtual void Dispose(bool disposing)
                        {
                            if(disposing)
                            {
                                // Release managed resources as well as unmanged ones.
                            }
                            else
                            {
                                // Release only unmanaged resources if they have not 
                                // been released already.
                            }
                        }
                        
                        public void Dispose()
                        {
                            Dispose(true);
                        
                            GC.SuppressFinalizer(this);  
                        }
                        

                        }

                        My impression, which is apparently wrong, is that it's up to you to call Dispose(). If you do, you should call Dispose(bool disposing), passing a true value indicating that the call is coming from Dispose() and not the finalizer. In addition, in our Dispose() method we tell the garbage collector not to call the finalizer since we've taken care of everything ourselves. However, if we forget to call Dispose(), the finalizer still gets called. In the finalizer, we call Dispose(bool disposing) passing the false value indicating that it's being called by the garbage collector and should only release any unmanaged resources that have not already been released. So what you're saying is that the garbage collector will call Dispose() in any case? [EDIT]Just to qualify things, I understand that Dispose() will be called automatically when using the, um, using construct. I'm wondering about other situations in which you may forget to call Dispose() yourself and you don't have the using construct taking care of it for you.[/EDIT]

                        O 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
                          Momony
                          wrote on last edited by
                          #76

                          Reason's why you might want an initialize and cleanup routines separate from constructors. 1) Your class has many constructors to handle argument type conversion, or allows multiple ways to "start-up" the object. In these situations, it is common to have a bunch of initialization code that is common to all of the constructors, and it is preferred to create 1 private function which all of the constructor's call after handling their special initialization circumstances. 2) Your class has some resources that have no performance penalty to declare, but have a significant performance penalty if they are going to be used, and there are many instances in which the class can be used without using the performance heavy resources. Then you would want to separate the initialization of the performance heavy resources to make it optional. I think an example of this is the CWnd class in MFC C++ 4.2. There are a lot of things you can do with a CWnd that don't require a Window Handle to be created (which causes a lot of OS overhead). Thus, the model was you construct a CWnd object, and if you wanted to use the features requiring a handle, then you called the create function. 3) For cleanup, sometimes you want you object to exist, but you want to free the resources independently. This usually happens when you are "reusing" an existing object instead of deleting the object and creating a new one. Thus, by calling a clean-up function, you can essentially "reinitialize" the object to the constructed state without having to reconstruct the object. I think these situations are rare, and not necessarily the best design, and usually occur in applications needing the highest performance. Performance is rarely a good argument for complicating a class design, but sometimes you really do need it. However, consistency of class design is a good thing in a project, so if all the classes are construct / initialize / clear / destruct that is better than some you do that way, and some you dont. Now the question of if the initialization and clear routines need to be public is another question. Hope this helps, -Kent

                          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
                            patbob
                            wrote on last edited by
                            #77

                            I learned as you. It prevents people from forgetting to init()/cleanup() the instances. If implemented right, it saves a lot of testing within the code to see if the object has been initialized, and if the initialization succeeded resulting in smaller, tighter, cleaner, easier to maintain code. ... of course, can't do it with C# since we no longer have the ability to control destruction timing. We're doomed to repeat, I guess.

                            patbob

                            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
                              Jacek Ostrowski
                              wrote on last edited by
                              #78

                              There is one important reason to use virtual Init() methods in C++ -- if you want to let descendant classes override initialization procedure, you cannot call it from constructor. C++ always completely constructs base class before it sets VMT pointer to the descendant class VMT, so it always calls virtual methods from the class being constructed. Delphi, for example, behaves differently -- you can call descendant class' virtual methods from constructor. jacostro

                              1 Reply Last reply
                              0
                              • L Leslie Sanford

                                objarni wrote:

                                Well -- Dispose() will be called by the garbage collector in any case -- so you don't really need to call it, unless you REALLY want to control the timing of the cleaning up of you resource.

                                Clearly I need to brush up on my .NET knowledge. I was under the impression that you must call Dispose yourself. Here's the pattern I've learned from .NET documentation, at least when the class that implements IDisposable can be used as a base class:

                                public class SomeClass : IDisposable
                                {
                                ~SomeClass()
                                {
                                Dispose(false);
                                }

                                protected virtual void Dispose(bool disposing)
                                {
                                    if(disposing)
                                    {
                                        // Release managed resources as well as unmanged ones.
                                    }
                                    else
                                    {
                                        // Release only unmanaged resources if they have not 
                                        // been released already.
                                    }
                                }
                                
                                public void Dispose()
                                {
                                    Dispose(true);
                                
                                    GC.SuppressFinalizer(this);  
                                }
                                

                                }

                                My impression, which is apparently wrong, is that it's up to you to call Dispose(). If you do, you should call Dispose(bool disposing), passing a true value indicating that the call is coming from Dispose() and not the finalizer. In addition, in our Dispose() method we tell the garbage collector not to call the finalizer since we've taken care of everything ourselves. However, if we forget to call Dispose(), the finalizer still gets called. In the finalizer, we call Dispose(bool disposing) passing the false value indicating that it's being called by the garbage collector and should only release any unmanaged resources that have not already been released. So what you're saying is that the garbage collector will call Dispose() in any case? [EDIT]Just to qualify things, I understand that Dispose() will be called automatically when using the, um, using construct. I'm wondering about other situations in which you may forget to call Dispose() yourself and you don't have the using construct taking care of it for you.[/EDIT]

                                O Offline
                                O Offline
                                objarni
                                wrote on last edited by
                                #79

                                Leslie Sanford wrote:

                                So what you're saying is that the garbage collector will call Dispose() in any case?

                                It will if a Dispose() call is placed in the Finalizer/destructor of the class (~DatabaseConnection in my case..) -- and that is the case if you follow the NET documentation pattern for implementing IDisposable:

                                public class SomeClass : IDisposable
                                {
                                ~SomeClass()
                                {
                                Dispose(false);
                                }
                                ...

                                .. so if you've followed that pattern, forgetting some Dispose() (or using-clauses equivalently) calls would not be that dramatic for your application. BUT: I'm still not 100% clear on the low-level semantics of GC/Dispose in .NET. Below is a link to a long technical discussion I'm reading up on just to be sure what I've said is correct. Otherwise, I have quite a lot of things to do next week at work ;) : http://www.thescripts.com/forum/thread214497.html A link within that discussion points to a "morale" of why/how Dispose came about, really interesting read. Apparently it's written by one of the original .NET designers: http://discuss.develop.com/archives/wa.exe?A2=ind0010A&L=DOTNET&P=R28572 -- modified at 15:26 Friday 10th August, 2007

                                1 Reply Last reply
                                0
                                • E ewasjdgb

                                  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 Offline
                                  B Offline
                                  brianhood
                                  wrote on last edited by
                                  #80

                                  constructor and the destructor or for memory management. init() is for class that have to many properties to pass in as arguments. unless you won't to use a config file/mem and decipher. ounces the object is constructed ,even if all it does is initialize the object to a NULL state, then you can set properties and call Init() the time the destructor in where you clean up,even if you got to call special function from the destructor, to keep the good clean.

                                  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.

                                    B Offline
                                    B Offline
                                    brianhood
                                    wrote on last edited by
                                    #81

                                    exactly: and in easier terms. constructor and the destructor or for memory management. init() is for class that have to many properties to pass in as arguments. unless you won't to use a config file/mem and decipher. ounces the object is constructed ,even if all it does is initialize the object to a NULL state, then you can set properties and call Init() ,the destructor in where you clean up,even if you got to call special function from the destructor, to keep the code clean.

                                    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)

                                      R Offline
                                      R Offline
                                      Rob Allan
                                      wrote on last edited by
                                      #82

                                      I believe the primary reason for this separation (which a few people have already suggested or hinted at) is that you can do something in your Init() function that you can't do in your constructor. Namely, you can call virtual functions and expect them to operate correctly! You can't do this in a constructor. To quote Scott Meyers in Effective C++: "You shouldn't call virtual functions during construction or destruction, because the calls won't do what you think, and if they did, you'd still be unhappy". You can read more about this at http://www.artima.com/cppsource/nevercall.html[^]. I have a friend who worked at a company that got so badly burned by bugs related to calling virtual functions from constructors, that they completely banned the use of constructors in all of their C++ code! This seems an extreme solution to me, but you get the point. To my mind constructors should be used to perform "simple" initialization -- initialize data members, allocate some memory, load resource strings, etc. If you need to do very complex initialization that involves calling other functions, then there may be an argument for breaking this out into a separate Init() function. If your initialization involves calling virtual functions, then it must be broken out into an Init() function to ensure it works reliably. Similar arguments would apply to destructors. Rob.

                                      1 Reply Last reply
                                      0
                                      • E ewasjdgb

                                        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.

                                        P Offline
                                        P Offline
                                        peggyjmoore
                                        wrote on last edited by
                                        #83

                                        It is useful to initialize simple member variables in a constructor. However, if the class that is being constructed needs to instantiate other objects (such as COM components or additional non-trivial classes or additional threads) then doing those kinds of operations in the constructor can cause major problems since the parent class is not yet completely formed. sweetpickle

                                        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)

                                          C Offline
                                          C Offline
                                          ChrisNic
                                          wrote on last edited by
                                          #84

                                          After following this discussion I come back to something that has been bothering me for some years now. Where is the good old top down method of programming where there were no classes and you solved everything with a gosub and a goto. These arcane problems with classes never came up then. And even back then, the programs still worked. Chris

                                          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