tags:

views:

282

answers:

6

Hi, I'm currently working on a sprite engine in C++. I have an abstract class IEngine with a virtual function init_api. This takes in a void*.

    // Initialise the engines' API
// api_params - void* to api parameters for initalisation
// hWnd - window handle
virtual bool init_api( void* api_params, HWND hWnd ) = 0;

I then have a DirectX implemented engine class CEngineDX. Which then casts api_params to a D3DPRESENT_PARAMETERS*, so it can be used for initialising DirectX.

//  Cast api_params to a D3DPRESENT_PARAMETERS
D3DPRESENT_PARAMETERS* presentParams = NULL;
presentParams = reinterpret_cast< D3DPRESENT_PARAMETERS* >( api_params );

I'm quite happy with this setup but wanted to get some other programmers view on this "solution" if you like.

Cheers for the replies!

Carl

+1  A: 

This is a relatively common problem with the variation of argument types in inheritance hierarchies; your subclass wants to specialize the type of 'api_params' from the parent class.

I think this is OK but it is C-like. I think better solution would be to make init_api non-virtual and implement it with the correct type in the subclass. Anyway, most likely the D3DPRESENT_PARAMETERS struct makes only sense with the DirectX engine, so why not have it in the subclass where it logically belongs to?

antti.huima
Thanks for your input. :P
Carl
A: 

I don't really like this API. Why use a void pointer? Why not make the first parameter a pointer or reference to D3DPRESENT_PARAMETERS? You know that is what it should be anyway right? This is more type-safe.

1800 INFORMATION
Thanks for your input. :P
Carl
A: 

Sorry I missed something out, I was wanting to have an openGL implementation of it as well using the same interfaces. So it's cross platform. If that makes any sense.

Carl
Are you going to need both implementations? Won't you be better off focusing on one or the other to begin with? Further, even if you want both to be supported, you could make it a static compile-time choice using template specialization to retain type safety, rather than runtime.
jalf
Thanks for the reply jalf. The only thing that put me off templates was I could not have init_api as a virtual function, upon reflection it probably would be best to do as you suggest. Cheers for the advice!
Carl
A: 

Thanks for your answers, much appreciated. :D

Carl
+1  A: 

Well, you could use templates (is you dislike casts), but your hierarchy will have to go in that case.

template<class T>
struct Engine {
   bool init_api(const T& params, HWND hWnd);
};

//specialize for DirectX
template<>
struct Engine <D3DPRESENT_PARAMETERS> {
  bool init_api(const D3DPRESENT_PARAMETERS& params, HWND hWnd) {
    return true;
  }
};

But, use something that fits into the grand scheme of things.

dirkgently
+1  A: 

Another way to do it is just have a common header and different *.cpp files for each implementation. That way you can include just the D3D or just the OGL files in your project. IMO its better to choose the API at compile time so your not linking against both libraries.

As for the void*, I don't really like it. I think you'd be better off defining your own types and then mapping them to the API types with wrapper structs / classes and typedefs. You can forward declare these, and put the actual implementation in your *.cpp files.

One other benefit of this method is that your not paying for virtual functions you don't need, although I realize the cost of a virtual call is pretty small.

BigSandwich