-
May 19th, 2009, 08:05 PM
#1
Is this "good" coding style... ?
I'm kind of new to C++, so I'm not sure if this is right. It doesn't really "seem" like all that great of an idea, but it was the best I could think of, and it's working how I want right now.
I'm trying to make a game. However, I would like it to be compatible across multiple operating systems. My solution was to create an class, EngineController, which needs implementation by a given operating system in order to work correctly.
class OSXController, for example, implements EngineController.
Currently, I have it so EngineController has a method StartEngine (protected visibility).
OSXController has a constructor/deconstructor. The constructor initializes libraries (I'm just using SDL for now), and then calls StartEngine. StartEngine keeps running until it breaks out its main while loop, and control transfers back to OSXController. This is where things get dodgy. OSXController calls its own deconstructor (it deletes its own reference). I come from a heavy Java background, so I'm used to things cleaning up after themselves...
Thanks for reading and taking the time to answer.
EDIT: I'm just using static methods now. It works out a lot better, couldn't quite figure out how to use them at the class level before. Anywho, is it still acceptable to use "delete this" within a class?
Last edited by Stachelsk; May 19th, 2009 at 08:26 PM.
-
May 19th, 2009, 10:01 PM
#2
Re: Is this "good" coding style... ?
I come from a heavy Java background, so I'm used to things cleaning up after themselves...
Don't try to make C++ behave like Java. Learn the appropriate C++ techniques (RAII, smart pointers and so on) and use them. Also, don't use new except when you absolutely need to, and you avoid the need for those in the first place.
Anywho, is it still acceptable to use "delete this" within a class?
I would say it's generally not a good idea, because if you're going to do that you have to enforce that the object can only be created via new (not on the stack, not global, not by new[]) or else you potentially will have major problems.
See: http://www.parashift.com/c++-faq-lit...html#faq-16.15
Last edited by Speedo; May 19th, 2009 at 10:03 PM.
-
May 20th, 2009, 02:27 AM
#3
Re: Is this "good" coding style... ?
Originally Posted by Stachelsk
class OSXController, for example, implements EngineController.
Currently, I have it so EngineController has a method StartEngine (protected visibility).
OSXController has a constructor/deconstructor. The constructor initializes libraries (I'm just using SDL for now), and then calls StartEngine.
While this is technically ok, I would consider it bad coding style ("it" referring to a constructor not returning after the object has been created and initialized).
Originally Posted by Stachelsk
StartEngine keeps running until it breaks out its main while loop, and control transfers back to OSXController. This is where things get dodgy. OSXController calls its own deconstructor (it deletes its own reference).
No way. The function which creates the OSXController destroys it. So your main function should look either like one of the below:
Code:
int main() {
#ifdef PLATFORM_OSX
OSXController controller;
#endif
controller.startEngine();
}
or
Code:
int main() {
EngineController * controller;
#ifdef PLATFORM_OSX
controller = new OSXController();
#endif
controller->startEngine();
delete controller;
}
The code between #ifdef and #endif is the platform specific part, you should add #elseif for the other platforms there. In the first example, the object is created on the stack and thus automatically removed at the end of main (yes, C++ automatically deletes objects !). In the second example, the object is created on the heap, thus it has to explicitly be deleted using "delete".
The advantage of the second example is that the controller variable is defined independently of the platform, which imho makes the code cleaner. You could actually replace the precompiler directives with C++ control statements (if (platform==1)). That wouldn't be possible in the first example.
so the best version that I would recommend would look more like this:
Code:
const unsigned int platform_osx = 0;
const unsigned int platform_win32 = 1;
// ...
#ifdef PLATFORM_OSX
const unsigned int platform = platform_osx;
// ...
#endif
int main() {
EngineController * controller;
if (platform == platform_osx)
controller = new OSXController();
elseif (platform == platform_win32)
controller = new Win32Controller();
// ...
controller->startEngine();
delete controller;
}
Last edited by treuss; May 20th, 2009 at 02:31 AM.
More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason - including blind stupidity. --W.A.Wulf
Premature optimization is the root of all evil --Donald E. Knuth
Please read Information on posting before posting, especially the info on using [code] tags.
-
May 20th, 2009, 03:30 AM
#4
Re: Is this "good" coding style... ?
Originally Posted by Stachelsk
I come from a heavy Java background, so I'm used to things cleaning up after themselves...
To build on treuss' last example, this can be achieved by a smart pointer (as mentioned by Speedo), assuming that your EngineController's derived classes have destructors that properly clean up after themselves (not with delete this, but say, by calling the necessary library functions), e.g.,
Code:
const unsigned int platform_osx = 0;
const unsigned int platform_win32 = 1;
// ...
#ifdef PLATFORM_OSX
const unsigned int platform = platform_osx;
// ...
#endif
std::auto_ptr<EngineController> createController()
{
if (platform == platform_osx)
return std::auto_ptr<EngineController>(new OSXController());
else if (platform == platform_win32)
return std::auto_ptr<EngineController>(new Win32Controller());
// ...
}
int main()
{
std::auto_ptr<EngineController> controller(createController());
// ...
controller->startEngine();
}
-
May 20th, 2009, 04:39 AM
#5
Re: Is this "good" coding style... ?
The problem with the solution above is that OSXController and Win32Controller would need to be implemented even on the other platforms.
with #defines you only need it to compile on the platform for which it is used.
One way you can do it is to have different files for a system and only include the one you actually want in the build dependent on the platform.
Then have a method getController() in each implementation which returns you the appropriate one.
-
May 20th, 2009, 08:29 AM
#6
Re: Is this "good" coding style... ?
On the broader topic of cross-platform game design....
Is your ultimate goal here to create a game, or a game engine? Unless you just want to create an engine for the fun of it, there's not a lot of point reinventing the wheel. There are tons of cross-platform libraries oriented towards game creation (OGRE for 3D rendering, OIS for input, Raknet for networking, OpenAL for sound, to name a few). If you actually want to make a game, you're much better off letting them worry about the platform specific details, while you just learn their API and make your game.
-
May 20th, 2009, 05:01 PM
#7
Re: Is this "good" coding style... ?
Originally Posted by Speedo
On the broader topic of cross-platform game design....
Is your ultimate goal here to create a game, or a game engine? Unless you just want to create an engine for the fun of it, there's not a lot of point reinventing the wheel. There are tons of cross-platform libraries oriented towards game creation (OGRE for 3D rendering, OIS for input, Raknet for networking, OpenAL for sound, to name a few). If you actually want to make a game, you're much better off letting them worry about the platform specific details, while you just learn their API and make your game.
I agree on there being no need to reinvent the wheel. However it is generally a good idea to hide the engine, or the parts of the engine that you use behind a layer of abstraction. This will allow you to easily change implementation.
For example, a game I am working on atm has a 2d renderer behind it. The renderer class is abstract so I can easily make an implementation that renders it 3d in the future instead. (without having to change the way the game works)
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|