Jump to content
  • Advertisement
Sign in to follow this  
fpsgamer

Design Pattern: Init &Tear Down Functions

This topic is 4353 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Lets say I have a class similar to this:
class CTest{
public:
CTest(){}
~CTest(){}

Init(); // allocate memory
TearDown(); // deallocate memory and stuff
};






Now I would perform something like this when I create an object and when I am through with it... CTest ct; c.Init(); c.TearDown(); or similarly... CTest* ct = new CTest(); ct->Init(); ct->TearDown(); But the thing is I could have easily placed Init() and TearDown() bodies inside the Constructor and Deconstructor. Having them as seperate functions means I have to rely on the caller to remember to do both of thoes things. What design pattern should I follow? edit: More trouble can follow if a person decides to use a member function that would rely on Init() having been called. If they decide to use another function without calling Init() first that would lead to dangerous behaviour .... But the question is still the same ... what is the proper design pattern?

Share this post


Link to post
Share on other sites
Advertisement
Why not put what needs to be initialized in the constructor, and what needs to be deinitialized in the destructor? This eliminates the possibility of the user initialized more than once or less than once.

Share this post


Link to post
Share on other sites
I prefer to have explicit Init/DeInit functions. That way I can return error codes if necessary, and try to deal with init calls failing. You can always call your init/deinit functions from within your c-tors and d-tors.

Share this post


Link to post
Share on other sites
If it's possible at all put them in constructor / destructor. If it's not possible I'd prefer rethinking the design so that it can be done.
The name of the pattern is raii (Resource Acquisition Is Initialization) btw, or more broadly resource management.

EDIT: One benefit of raii is that, if done properly, there will be no leaks or whatever even in the face of exceptions.

Share this post


Link to post
Share on other sites
Quote:
Original post by agi_shi
Why not put what needs to be initialized in the constructor, and what needs to be deinitialized in the destructor? This eliminates the possibility of the user initialized more than once or less than once.


Thats what I thought, but I'm reading a book which has code examples/tutorials from "real programmers" exhibiting this pattern.

This seems like a very "C" thing to do and doesnt look like a good idea in "C++"

But more importanly should one have to design classes as though the people using them are going to be idiots? Or should they be idiot proof?

Share this post


Link to post
Share on other sites
Quote:
Original post by fpsgamer
Quote:
Original post by agi_shi
Why not put what needs to be initialized in the constructor, and what needs to be deinitialized in the destructor? This eliminates the possibility of the user initialized more than once or less than once.


Thats what I thought, but I'm looking at code examples/tutorials from "real programmers" exhibiting this pattern.

This seems like a very "C" thing to do and doesnt look like a good idea in "C++"

But more importanly should one have to design classes as though the people using them are going to be idiots? Or should they be idiot proof?


In my opinion if you code something in C++ to use by somebody else, you simply assume they are not idiots. Programming, and certainly in C++, is difficult enough. So whatever helps automate some tasks and reduce complexity is welcome for anybody. Just look at how many bugs exist in software, I think raii helps a lot and it can be done in a good way in C++.

Share this post


Link to post
Share on other sites
It only makes sense to separate the initialization from the constructor if, in the course of normal operation, it's reasonable for the initialization to fail. The text book example is the file object, where opening the file can reasonably fail in the course of normal operation. Otherwise, if the initialization is expected to succeed and the initialization is required before using any of the member functions, then there's no reason to separate initialization from construction.

Share this post


Link to post
Share on other sites
Quote:
Original post by Driv3MeFar
I prefer to have explicit Init/DeInit functions. That way I can return error codes if necessary, and try to deal with init calls failing. You can always call your init/deinit functions from within your c-tors and d-tors.


Are the problems that your return codes indicate exceptional? As in, are they an exception to what should happen?

In that case you use exceptions:

class a { public:
a(): b(makeC()) {
if (b == NULL) // oh no!
throw std::runtime_error("b == NULL"); // throw exception
}

~a() {
// b will be freed by the auto_ptr when the auto_ptr gets destroyed
}

private: std::auto_ptr<c> b;

...
};

int main() {
try { // check for exceptions
a A;
A.doAwesomeStuff();
}
// catch std::exception s. note: std::runtime_error is an std::exception
catch(std::exception& e) { std::cout << e.what(); }
// catch anything else
catch(...) { std::cout << "unknown error"; }
}






Read More.

Share this post


Link to post
Share on other sites
And then you end up with a half-initialized object, if you are not very very careful.
See:
http://www.awprofessional.com/content/images/020163371x/supplements/Exception_Handling_Article.html

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!