Well, I've only recently started doing cross-platform stuff (currently win32 and linux) so I still have some questions over how to better design things. I'll start off with a simple example and list the possibilities that occurred to me. Please let me know if I missed something and feel free to suggest better ideas.
So I am developing a window class that will create a plain vanilla main application window that will later be used to render things. Currently I'm dealing with a win32 and X implementations but let's suppose that I can later port to Mac or some other random XYZ platform.
Take 1.
// Window.h
class Window
{
public:
Create();
#ifdef _WIN32
SetIcon(HANDLE); // Just an example
#endif
#ifdef _LINUX
SetIcon(ICONMAP); // Just an example
#endif
};
// Window.cpp
#ifdef _WIN32
// Implement one way
#endif
#ifdef _LINUX
// Implement another way
#endif
This is the most basic way of doing things. Needless to say this way sucks. If I want to add an implementation I have to modify both the header file and the source file, they will get rather large, confusing, hard to read and maintain.
Take 2.
A simple improvement is separating Window.cpp into Win32Window.cpp and XWindow.cpp. Depending on the platform the project will be compiled with a different file. This is a little better but we're still stuck with a header file that has to modified if we decide to add implementations. Note, I am purposely not abstracting the icon (I'm just trying to illustrate the fact that some implementations may need specialized methods that don't really apply to other implementations). So let's move on.
Take 3.
// BasicWindow.h
class BasicWindow
{
// ...
};
// XWindow.h
class XWindow : public BasicWindow
{ /* ... */};
// Win32Window.h
class Win32Window : public BasicWindow
{ /* ... */};
// Window.h
#ifdef _WIN32
typedef Win32Window Window;
#endif
#ifdef _LINUX
typedef XWindow Window;
#endif
So far this is the best solution but it still suffers from one problem. If I add virtual functions to BasicWindow (say, Create() = 0;) the user of these classes will pay a runtime penalty eventhough all decisions about types can be made at compile time. In the case of this class it's acceptable, but I'd still like to know of a better solution that avoids this problem. Any suggestions are welcome.