another preference question....
-
You're references will not be collected, they just might have been finalized if they also have a finalizer. You can even revive references from finalizers. But you should never call another object's Dispose() method from a finalizer - if that object needs to do cleanup, it should have its own finalizer.
Daniel Grunwald wrote:
You're references will not be collected, they just might have been finalized if they also have a finalizer. You can even revive references from finalizers. But you should never call another object's Dispose() method from a finalizer - if that object needs to do cleanup, it should have its own finalizer
Thanks for the clarification. I appreciate it.
-
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)
I have not previously encountered this approach (and I have been coding professionally for nearly fourteen years). I disagree with the separate init() method approach for a number of reasons: a.) Expectations (one should follow convention) - most frameworks will initialise objects through the constructor, and users of your code (who can even be your co-workers or your future co-workers) are likely to expect that too. They will easily do something wrong if the class usage semantics are unconventional. b.) You create an additional source of failure (read source of bugs), because nother method must be called before the object can be used. Omission of this call can create a hard to track down bug. Why create this possibility? c.) Error checking. You have created an additional state for your objects to exist in. You have made it possible to use your class without it being initialised, and so you ALWAYS have to ensure that when a public method is called the object has been correctly initialised. Usually you would only have to place guards on the methods that are intended to modify the object's contents in order to ensure that the contents are valid. If your object can be inherited from (this is C++ so unless you only construct objects through a factory method, your class can be inherited from), then you have to place guards in the protected methods as well. Ugly! d.) Calling init() (or whatever you call it) multiple times becomes possible but probably does not make sense. If you need this capability for the object, then you are either reset()ing the object, or you need to construct a new one. e.) Copy constructors - when copy semantics are needed for a class, the constructor has to create a fully initialised object. This breaks the paradigm. f.) C++ will chain the calling of constructors. The compiler will tell you if you get the chaining wrong. You will have to implement this manually if you use an init() method, and there will be no compile-time errors to tell you that you got it wrong. It's even more error prone when you are using multiple inheritance. You have once again created a source of potentially hard-to-find bugs. Why? g.) Performance - initialising attributes within a constructor (especially within the member initialisation list) is more efficient than initialising them from a separate method. If performance is any concern, you will almost certainly want the constructor to do it all. h.) If you absolutely must perform initialisation in a separate method, make the method
-
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)
Generally I think it's best to have the constructor/destructor perform the intilisation/clean up. Breaking the code out into an init procedure which is called from the constructor(s) can be useful for sharing similar code between constructors but otherwise it's a personal preference thing... However, there are times when init/cleanup methods are required. One example is when you want to support some kind of object pooling mechanism, in which case you'll want to be able to clean up the class without it be 'finalized' and you'll want to be able to re-initialize it when it's retreive back out of the pool - at which point the constructor is useless since the object has already been created. If initialisation is expensive, then you may also want to be able to create X number of classes in the pool (on startup for example) and allow the initialization to take place 'lazily' after the fact. Also, the 'clean up' style methods may be needed depending on what language you're working in. In something like C# where there is no deterministic finalization you need an explicit clean up method on some objects to allow immediate release of unmanaged resources (hence the IDisposable interface, which is really just a system supported way of implementing a clean up method). In VB6, circular references between classes could be a problem, in which case a clean up method would sometimes be needed to release at least one set of references so memory wasn't leaked and the classes did actually get 'finalized' eventually. I can't think of another instance when 'init' style methods are useful, except for the object pooling, although that might just be lack of imagination on my part :) Basically, I think it depends on that particular patterns and architecture you're using, but for mmost classes the constructors/destrutors are the right place for init/cleanup code.
-
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 :)
I have two solutions for those classes (and of course, no other human being has ever thought about this extremely clever solution:->). - a status function that checks invariants (mostly as simple as a fail or success flag) -- is_ok() - a static factory, mostly returning a std::pair (or just object*). This requires that one hides the c'tors (except assignment and copy -- falling back to is_ok()) auto_ptr f(new Foo(bar)); if(f->is_ok())... or auto_ptr f(Foo::create(bar)); if(f/* && f->is_ok()*/)... or pair> r(Foo::create(bar)); if(r->first == BAD_DOG) //drooled on the ham...:omg:
-
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)
In my experience, I've always wanted my classes ready to use from the time they are created. If I want a null instance, I create a null constructor. If I want the fields populated, I create an overloaded constructor that does that. I used to build separate routines that performed similar functions as yours, but tracking what did what became too much of a maintenance overhead. Once I began overloading the constructors, management became a lot easier. I'm not saying that I didn't refactor, because I did and I do. If I had redundant initialization code, I pulled them out into their own methods. But, I do not automatically pull out initialization just for the sake of pulling it out, because it's "easier to test," which, by the way, really doesn't make it any easier. It just creates additional, unnecessary function points... My $0.02...
-
Generally I think it's best to have the constructor/destructor perform the intilisation/clean up. Breaking the code out into an init procedure which is called from the constructor(s) can be useful for sharing similar code between constructors but otherwise it's a personal preference thing... However, there are times when init/cleanup methods are required. One example is when you want to support some kind of object pooling mechanism, in which case you'll want to be able to clean up the class without it be 'finalized' and you'll want to be able to re-initialize it when it's retreive back out of the pool - at which point the constructor is useless since the object has already been created. If initialisation is expensive, then you may also want to be able to create X number of classes in the pool (on startup for example) and allow the initialization to take place 'lazily' after the fact. Also, the 'clean up' style methods may be needed depending on what language you're working in. In something like C# where there is no deterministic finalization you need an explicit clean up method on some objects to allow immediate release of unmanaged resources (hence the IDisposable interface, which is really just a system supported way of implementing a clean up method). In VB6, circular references between classes could be a problem, in which case a clean up method would sometimes be needed to release at least one set of references so memory wasn't leaked and the classes did actually get 'finalized' eventually. I can't think of another instance when 'init' style methods are useful, except for the object pooling, although that might just be lack of imagination on my part :) Basically, I think it depends on that particular patterns and architecture you're using, but for mmost classes the constructors/destrutors are the right place for init/cleanup code.
I too favour doing all that's needed to make an object usable within it's constructor and doing the reverse in it's destructor. However there are situations where stuff needs to get done before the object is put to good use, but the information required is not available at construct time. An example that springs to mind is editors that have methods such as PrepareEditingControlForEdit - are such methods inits() in another guise. In another case I've seen class constructors send messages to a remote object, mark the object they've just built as being unusable and terminate. The object itself remains practically unusable until it get's a response from the remote object and completes its initialisation with the information provided therein, whereupon it raises an ReadyToUse event on itself.
-
peterchen wrote:
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.
Yes, that's where RIAA comes into play. :)
peterchen wrote:
But Joergen! That's why there is shared_ptr!
Well, that works wonders, if it's a pointer to a handle. That is not always the case. MFC and ATL/WTL objects come to mind.
-- Larva-Tested, Pupa-Approved
Joergen Sigvardsson wrote:
RIAA
But you mean RAII, of course. Perhaps _the_ most important four-letter word in OO/C++. :rolleyes:
-- Time you enjoy wasting is not wasted time - Bertrand Russel
-
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.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(); ...
-
Generally I think it's best to have the constructor/destructor perform the intilisation/clean up. Breaking the code out into an init procedure which is called from the constructor(s) can be useful for sharing similar code between constructors but otherwise it's a personal preference thing... However, there are times when init/cleanup methods are required. One example is when you want to support some kind of object pooling mechanism, in which case you'll want to be able to clean up the class without it be 'finalized' and you'll want to be able to re-initialize it when it's retreive back out of the pool - at which point the constructor is useless since the object has already been created. If initialisation is expensive, then you may also want to be able to create X number of classes in the pool (on startup for example) and allow the initialization to take place 'lazily' after the fact. Also, the 'clean up' style methods may be needed depending on what language you're working in. In something like C# where there is no deterministic finalization you need an explicit clean up method on some objects to allow immediate release of unmanaged resources (hence the IDisposable interface, which is really just a system supported way of implementing a clean up method). In VB6, circular references between classes could be a problem, in which case a clean up method would sometimes be needed to release at least one set of references so memory wasn't leaked and the classes did actually get 'finalized' eventually. I can't think of another instance when 'init' style methods are useful, except for the object pooling, although that might just be lack of imagination on my part :) Basically, I think it depends on that particular patterns and architecture you're using, but for mmost classes the constructors/destrutors are the right place for init/cleanup code.
I strongly dislike the create-and-then-initialize usage; as a general rule, I always leave the object in a well-known usable state after a new, so I support the initialization-as-sinonym-for-creation point of view. Actually, when I have the authority to set coding standards in the team I require that one of the tests the class must pass be a call to each of it's methods right after object creation to verify there are no internal state management issues unsolved. If your object requires a multi step initialization, which means it's a state-based class, I write another class that handles the creation (and the rest of it's state management, for that matter) of the "complex" one, in a way that that the "main app" code doesn't have to know "everything about everything". Te complexity is hidden in the "creator". In pattern language, that's called inversion of control (IoC). That's what the Factory pattern's "Create" methods are used generally for, instead of the "a = New A" approach. It hides the complexities associated to object creation. When an object instance has not-so-trivial-to-manage dependencies (memory, device or whatever they are) call the specialist. That's where we could get talking about Dependency Injection, but that's another story. So, even if your dependencies are trivial, call the specialist. I still haven't found a situation where that approach hasn't fit for me, so I keep applying the rule. I think any help to isolate and hide complexity from code structure must be the first issue from a developer point of view -from an analyst's it is to perform whatever task it's supposed to!). Also, that "constructor" class is the perfect place to comment the whole tricky part of the initialization, actually it should be the only place where any comment on it should appear. Of course, all this is just my opinion, although I think it's an informed one :) "I disagree with your every single word, but I'll defend to death your right to say them." - Voltaire
-
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
I like.
-- Time you enjoy wasting is not wasted time - Bertrand Russel
-
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.
Janzen wrote:
the pattern
OT: I think RAII is mostly considered to be an idiom, not a pattern.
-- Time you enjoy wasting is not wasted time - Bertrand Russel
-
Daniel Grunwald wrote:
If the Create() method can return derived classes, I would put it in a factory class and not in the base class
I agree. Like I said, it was a terrible contrived example, and after I posted it I realized how bad it actually was! Having a base class create derived classes would be a complete WTF... :-O
Sunrise Wallpaper Project | The StartPage Randomizer | A Random Web Page
Miszou wrote:
Having a base class create derived classes would be a complete WTF
Well, you're not the first who wrote something like that. Take a look at System.Net.WebRequest.Create...
-
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)
Regarding the original question, at uni we learnt to do all this in the constructor. Well, it's just a uni @ Greece... I often separate it into different methods (create data bindings, load a tree etc), but still they are all called from the constructor, except from cases of winforms where you have a constructor and a Load.
-
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)
By the very nature of it being a constructor it is supposed to construct the object. Now what ever language you use it should be in a valid state after construction, but there are some things that incure too much of an overhead to be placed inside a constructor. I would avoid starting threads or calling services in there as it makes it very hard to use in the calling code as you may want to pass the reference around. Having said that the behaviour of the class may change if a thread is not started so either well document it, and/or think about more about how the class is going to be used and design it accordingly. ;)
-
Joergen Sigvardsson wrote:
RIAA
But you mean RAII, of course. Perhaps _the_ most important four-letter word in OO/C++. :rolleyes:
-- Time you enjoy wasting is not wasted time - Bertrand Russel
:laugh: I don't know how I got those two mixed up. Frankly speaking, that's scary! :-D
-
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)
One advantage of using the Init() method comes from being able to subscribe to the an Event that is fired when the class values are initiated. If you want an series of events to fire immediately after the class has been initialized this would not be possible using a constructor. Using an Init() you can create the class, subscribe events and then populate the data. So imagine that you new class is passed through a set of methods, you may not know at what time within the methods it is being populated but you can still capture the event a perform some action upon it. To be honest I have yet to use this type of setup and have found that using constructors is more than sufficient.
-
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)
Just about everything to do with software design is a matter of opinion. Never feel that your's is worth less than other people's just because you didn't go to college. I never studied formally either. Everything I know about software design has been self taught or learned on the job. I've worked with lots of other developers since i started in this profession, and I find that it's real experience that counts here, not paper qualifications!
-
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)
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
-
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
returnsNULL
, so there is nothing to calldelete
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 placementnew
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 thevtbl
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 placementnew
, 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 -
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)
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