Are (apparently) shady things ever acceptable for practical reasons?
First, some code on my code. I am writing a graphics module for my 2D game. My module contains more than two classes, but I will focus only on two: Font and GraphicsRenderer.
The font provides an interface with which you can download (and release) files and nothing more. In my Font header, I don't want any implementation details to leak, and this includes the data types of the third-party library that I use. The way I prevent the third-party library from being visible in the header goes through an incomplete type (I understand that this is standard practice):
class Font
{
private:
struct FontData;
boost::shared_ptr<FontData> data_;
};
GraphicsRenderer is a device (read: singleton) that initializes and exits a third-party graphics library, and is also used to render graphic objects (such as fonts, images, etc.). The reason for this is because, as I said, the class initializes a third-party library automatically; it does this when the singleton object is created and exits the library when the singleton is destroyed.
In any case, in order for GR to render Font, it must have access to its FontData object. One option would be to have a public getter, but this would provide an implementation of Font (no other class except Font and GR should care about FontData). Instead, I found it better to make GR a font friend.
. , (singleton friend), , . , , , GR , , , , .
. , GR Font:: data_, , , FontData ( , )? , ...
struct Font::FontData
: public sf::Font
{
};
void GraphicsRenderer::printText(const Font& fnt )
{
struct FontDataSurogate
: public sf::Font {
};
FontDataSurogate* suro = (FontDataSurogate*)fnt.data_.get();
sf::Font& font = (sf::Font)(*suro);
}
, . , , , , , , - , , , .:) ( , , .)