I have a class setup that I have converted to use pimpl, something like this:
(outline only, I'm aware this doesn't compile)
struct GAME
{
unique_ptr<GAME_IMPL> _impl;
explicit GAME() : _impl( new GAME_IMPL( *this ) );
IMAGES getImages() { return _impl._images; }
};
struct GAME_IMPL
{
IMAGES _images;
PLAYER _player;
explicit GAME_IMPL( GAME& game ) : _player( game ) { }
};
struct PLAYER
{
SPRITE _sprite;
explicit PLAYER( GAME& game ) { _sprite.load( game.getImages() ); }
};
Before I converted to a pimpl pattern, this was fine.
_sprite.load( game.getImages() )
could access GAME::_images
because GAME::_images
instantiates before GAME::_player
.
However, after converting to pimpl, you can see that _sprite.load( game.getImages() )
will fail - PLAYER
cannot access GAME::_images
, because GAME::getImages
uses GAME::_impl
, which is not assigned until after all of GAME_IMPL
has been constructed.
Obviously my example is contrived. But is there some way to allow the _impl
pointer to be set before or while the GAME_IMPL
object is still being constructed?
I considered the following:
- Passing
PLAYER
only the necessary elements. This is messy since it involves modifying the API ofPLAYER::PLAYER
every time I adjustPLAYER
's fields. Also in practicePLAYER
's constructor may end up taking 30 odd parameters. - Using a two-stage initialisation, e.g.
PLAYER::PLAYER()
,PLAYER::Load()
- this is even more messy since it means converting references to pointers throughout. - Passing
PLAYER
GAME_IMPL
instead - this loses any benefits of using pimpl in the first place.