Let's say I want to make some sort of engine which should support loading graphical Image
s, so I have
struct Image;
Image* load_image_from_file(...);
I don't want external world to know what Image
really is, they'll deal only with pointers to it.
However inside engine
I want to use specific type, e.g. SDL_Surface
which is fully defined in SDL.
Can I somehow redifine Image for this file so compiler assumes SDL_Surface*
each time it sees Image*
(other than macro)?
I.e. I want something like typedef struct SDL_Surface Image;
All attempts like
using Image = SDL_Surface;
typedef SDL_Surface Image;
typedef struct SDL_Surface Image;
produce compile time error (http://codepad.org/1cFn18oh).
I know that I can use something like struct Image{SDL_Surface* surface};
in engine.c
/engine.cpp
but it creates unnecessary indirection and I'll have to type ->surface
.
Another dirty solution is to use explicit casts, e.g.((SDL_Surface*)image)
but I'm interesting in cleaner renaming.
PS. I'm interested in answers for both C and C++.
Simply define an alias:
using Image = SDL_Surface;
typedef SDL_Surface Image;
which compiles just fine.
If you need to hide SDL_Surface
, just import it into some anonymous or detail
-named namespace and use it like this.
If, for some reasons, you want to define your own Image
type, you can always declare a(n) (implicit) conversion function/operator, like:
struct Image {
/* explicit */ operator SDL_Surface() const;
// ...
};
and also back to Image
, if you need that:
struct Image {
/* explicit */ Image(SDL_Surface&&);
/* explicit */ Image(SDL_Surface const&);
// ...
};
In C++ you can use the inheritance:
// User view
struct Image; // forward declaration (inclomplete type).
Image* LoadFromFile (...); // You can use pointer to incomplete type
// Implementation view
struct Image: SDL_Surface { }; // here you go !! :-)
Remark: it would be safer to use classes and private inheritance, so that only Image knows that it is an SDL_Surface.
In some cases it could be undesirable to to inherit from an existing implementation class (for example if you'd need a virtual destructor and the base class doesn't). Then the PIMPL idiom could be an alternative (at the cost of an additional indirection):
//User View unchanged
struct Image;
int TestImage(Image*z);
//implementation view
struct Image {
struct ImageImpl { int x; }; // nested definition or typedef or whatever
ImageImpl *p; // works in every case, at cost of an extra indirection instead of a pointer
};
int TestImage(Image* z)
{
return z->p->x;
}
The main advantage of PIMPL here, is that you could expose more than just an incomplete type, and hence offer to the clients some useful member functions. But if you don't need this, and as you already work with poitners to the object on the client side, you could as well go directly to composition and have an ImageImpl
member instead of a PIMPL pointer.
In C, you can't use inheritance. But composition would certainly do the trick:
struct Image {
SDL_Surface s;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With