Separating public interface from implementation details - c++

I have to design a Font class that will have multiple implementations spanning platforms or different libraries (Win32 GDI or FreeType for example). So essentially there will be single shared header/interface file and multiple .cpp implementations (selected during build time). I would prefer to keep the public interface (header file) clean from any implementation details, but this usually is hard to achieve. A font object has to drag some sort of a private state - like a handle in GDI, or FreeType face object internally.
In C++, what is the best way to track private implementation details? Should I use static data in implementation files?
Edit: Found this great article on the subject: Separating Interface and Implementation in C++.
p.s. I recall in Objective-C there are private categories that allow you to define a class extension in your private implementation file making quite elegant solution.

You can use the PIMPL design pattern.
This is basically where your object holds a pointer to the actual platform dependent part and passes all platform dependent calls through to this object.
Font.h
class FontPlatform;
class Font
{
public:
Font();
void Stuff();
void StuffPlatform();
private:
FontPlatform* plat;
};
Font.cpp
#include "Font.h"
#if Win
#include "FontWindows.h"
#else
#error "Not implemented on non Win platforms"
#endif
Font::Font()
: plat(new PLATFORM_SPCIFIC_FONT) // DO this cleaner by using factory.
{}
void Font::Stuff() { /* DoStuff */ }
void Font::StuffPlatform()
{
plat->doStuffPlat(); // Call the platform specific code.
}

Related

UML notation for C++ Link Seam (shared header with different implementation)

In a C++ cross-platform library,
we use shared headers which are compiled with different module versions for each OS.
A.k.a Link-Seam
//Example:
//CommonHeader.h
#ifndef COMMON_HEADER_H
#define COMMON_HEADER_H
class MyClass {
public:
void foo();
}
#endif
.
//WindowsModule.cpp
#include "CommonHeader.h"
void MyClass::foo() {
//DO SOME WINDOWS API STUFF
printf("This implements the Windows version\n");
}
.
//LinuxModule.cpp
#include "CommonHeader.h"
void MyClass::foo() {
//DO SOME LINUX SPECIFIC STUFF HERE
printf("This implements the Linux version\n");
}
Of course, in each build you only select one module, respective to the environment you are using.
This is meant to suppress the indirect call to the functions
My Question is: How to note this relationship in UML ?
"Inheritance"? "Dependency"? "Note"?
class MyClass {
public:
void foo();
}
This is nothing more than a class contract, so basically an interface which you realize in different modules. To visualize that, you can use interface realization notation (like a generalization, but with dashed lines).
The reality is I think that you’ve got only one class in a UML class diagram, being MyClass, with a public operation foo(); it’s just that you have two code implementations of this class, one for Linux and one for Windows. UML Class models are not really setup to answer the question of how you implement this, in your case using c++ with header files: Imagine if instead you in-lined your functions and ended up writing two inline implementations of MyClass, one for Linux and one for Windows. Logically you still have one class in your class diagram (but with two implementations) and the header file (or lack thereof) wouldn’t come into it. What you need therefore is a way to show a how the C++ is structured, not a way to show the logical class constructs. I’m not aware of a specific way in UML to represent code structure, however you could build a code structure model using Artefacts maybe (?) which could denote the c++ file structures.
It could be seen as some kind of "inheritance". There is however no relation between classes as there is just one class - so there is no relation between two. The actual construct of using platform dependent implementation however imitate relation "is a".

Design pattern: C++ Abstraction Layer

I'm trying to write an abstraction layer to let my code run on different platforms. Let me give an example for two classes that I ultimately want to use in the high level code:
class Thread
{
public:
Thread();
virtual ~Thread();
void start();
void stop();
virtual void callback() = 0;
};
class Display
{
public:
static void drawText(const char* text);
};
My trouble is: What design pattern can I use to let low-level code fill in the implementation?
Here are my thoughs and why I don't think they are a good solution:
In theory there's no problem in having the above definition sit in highLevel/thread.h and the platform specific implementation sit in lowLevel/platformA/thread.cpp. This is a low-overhead solution that is resolved at link-time. The only problem is that the low level implementation can't add any member variables or member functions to it. This makes certain things impossible to implement.
A way out would be to add this to the definition (basically the Pimpl-Idiom):
class Thread
{
// ...
private:
void* impl_data;
}
Now the low level code can have it's own struct or objects stored in the void pointer. The trouble here is that its ugly to read and painful to program.
I could make class Thread pure virtual and implement the low level functionality by inheriting from it. The high level code could access the low level implementation by calling a factory function like this:
// thread.h, below the pure virtual class definition
extern "C" void* makeNewThread();
// in lowlevel/platformA/thread.h
class ThreadImpl: public Thread
{ ... };
// in lowLevel/platformA/thread.cpp
extern "C" void* makeNewThread() { return new ThreadImpl(); }
This would be tidy enough but it fails for static classes. My abstraction layer will be used for hardware and IO things and I would really like to be able to have Display::drawText(...) instead of carrying around pointers to a single Display class.
Another option is to use only C-style functions that can be resolved at link time like this extern "C" handle_t createThread(). This is easy and great for accessing low level hardware that is there only once (like a display). But for anything that can be there multiple times (locks, threads, memory management) I have to carry around handles in my high level code which is ugly or have a high level wrapper class that hides the handles. Either way I have the overhead of having to associate the handles with the respective functionality on both the high level and the low level side.
My last thought is a hybrid structure. Pure C-style extern "C" functions for low level stuff that is there only once. Factory functions (see 3.) for stuff that can be there multiple times. But I fear that something hybrid will lead to inconsistent, unreadable code.
I'd be very grateful for hints to design patterns that fit my requirements.
You don't need to have a platform-agnostic base class, because your code is only compiled for a single concrete platform at a time.
Just set the include path to, for example, -Iinclude/generic -Iinclude/platform, and have a separate Thread class in each supported platform's include directory.
You can (and should) write platform-agnostic tests, compiled & executed by default, which confirm your different platform-specific implementations adhere to the same interface and semantics.
PS. As StoryTeller says, Thread is a bad example since there's already a portable std::thread. I'm assuming there's some other platform-specific detail you really do need to abstract.
PPS. You still need to figure out the correct split between generic (platform-agnostic) code and platform-specific code: there's no magic bullet for deciding what goes where, just a series of tradeoffs between reuse/duplication, simple versus highly-parameterized code, etc.
You seem to want value semantics for your Thread class and wonder where to add the indirection to make it portable. So you use the pimpl idiom, and some conditional compilation.
Depending on where you want the complexity of your build tool to be, and if you want to keep all the low level code as self contained as possible, You do the following:
In you high level header Thread.hpp, you define:
class Thread
{
class Impl:
Impl *pimpl; // or better yet, some smart pointer
public:
Thread ();
~Thread();
// Other stuff;
};
Than, in your thread sources directory, you define files along this fashion:
Thread_PlatformA.cpp
#ifdef PLATFORM_A
#include <Thread.hpp>
Thread::Thread()
{
// Platform A specific code goes here, initialize the pimpl;
}
Thread::~Thread()
{
// Platform A specific code goes here, release the pimpl;
}
#endif
Building Thread.o becomes a simple matter of taking all Thread_*.cpp files in the Thread directory, and having your build system come up with the correct -D option to the compiler.
I am curious, what would it be like to design this situation like the following (just sticking to the thread):
// Your generic include level:
// thread.h
class Thread : public
#ifdef PLATFORM_A
PlatformAThread
#elif PLATFORM_B
PlatformBThread
// any more stuff you need in here
#endif
{
Thread();
virtual ~Thread();
void start();
void stop();
virtual void callback() = 0;
} ;
which does not contain anything about implementation, just the interface
Then you have:
// platformA directory
class PlatformAThread { ... };
and this will automatically result that when you create your "generic" Thread object you automatically get also a platform dependent class which automatically sets up its internals, and which might have platform specific operations, and certainly your PlatformAThread class might derive from a generic Base class having common things you might need.
You will also need to set up your build system to automatically recognize the platform specific directories.
Also, please note, that I have the tendency to create hierarchies of class inheritances, and some people advise against this: https://en.wikipedia.org/wiki/Composition_over_inheritance

Multiplatform class design C++

I have had an idea for a non standard way to handle multiplatform interfaces in C++ and would like to know if that is generally a bad idea and why.
Currently I can only think of one disadvantage: It is very(?) uncommon do to something like that and maybe its not obvious how it works on first sight:
I have a class that will be used on different platforms, for example CMat4x4f32 (4x4 matrix class using 32 bit floats).
My platform independent interface looks like this:
class CMat4x4f32
{
public:
//Some methods
#include "Mat4x4f32.platform.inl"
};
Mat4x4f32.platform.inl looks like this:
public:
// Fills the matrix from a DirectX11 SSE matrix
void FromXMMatrix(const XMMatrix& _Matrix);
It just adds a platform depending interface to the matrix class.
The .cpp and the Mat4x4f32.platform.inl are located inside subfolders like "win32" or "posix" so in win32 I implement the FromXMMatrix function. My buildsystem adds these subfolders to the include path depending on the platform I build for.
I could even go a step beyond and implement a .platform.cpp that is located inside win32 and contains only the functions I add to the interface for that platform.
I personally think this is a good idea because it makes writing and using interfaces very easy and clean.
Especially in my Renderer library that heavily uses the Matrix class from my base library I can now use platform depending functions (FromXMMatrix) in the DirectX part as if I dont have any other platforms to worry about.
In the base library itself I can still write platform independent code using the common matrix interface.
I also have other classes where this is useful: For example an Error class that collects errors and automatically translates them into readable messages and provide some debugging options.
For win32 I can create error instances from bad DirectX and Win32 HResults and on Linux I can create them from returned errno's. In the base library I have a class that manages these errors using the common error interface.
It heavily reduces code required and prevents having ugly platform depending util classes.
So is this bad or good design and what are the alternatives?
It sounds like you're talking about using the bridge pattern:
http://c2.com/cgi/wiki?BridgePattern
In my personal experience I've developed a lot of platform independent interfaces, with specific implementations using this pattern and it has worked very well, I've often used it with the Pimpl idiom:
http://c2.com/cgi/wiki?PimplIdiom
As in alternatives I've found that this site in general is very good for explaining pros & cons of various patterns and paradigms:
http://c2.com/cgi/wiki
I would recommend you used "pimpl" instead:
class CMat4x4f32
{
public:
CMat4x4f32();
void Foo();
void Bar();
private:
std::unique_ptr<CMat4x4f32Impl> m_impl;
};
And then in build-file configs pull in platform specific .cpp files, where you for instance define your platform specific functions:
class CMat4x4f32::CMat4x4f32Impl
{
public:
void Foo() { /* Actual impl */ }
void Bar() { /* Actual impl */ }
// Fills the matrix from a DirectX11 SSE matrix
void FromXMMatrix(const XMMatrix& _Matrix);
};
CMat4x4f32::CMat4x4f32() : m_impl(new CMat4x4f32Impl()) {}
CMat4x4f32::Foo() { m_impl->Foo(); }
CMat4x4f32::Bar() { m_impl->Bar(); }

C++, two classes with mutual needs

I have converted a scientific simulation platform from Java into C++. I have tried to keep the design as much as possible the same as previous implementation. In java because of the late binding, circular dependencies are resolved at the run time. However, circular dependencies have created a hell of a mess in C++.
Is there an automated tool which analyses and lists the circular includes and references? (Visual Studio 2010 only issues a huge list of nonsense errors).
I have tried to use forward references wherever possible. However in some occasions both classes need functionality of the other class (i.e. call to methods which makes it impossible to use forward reference). These needs exist in Logic and if I radically change the design they will no more represent real world interactions.
How could we implement two classes which need each other's methods and status? Is it possible to implement them in C++?
Examples:
Example 1: I have a class called "World" which creates Objects of the type "Agent". Agent needs to call World methods to get information of its environment. World also needs to iterate through Agents and execute their "run" method and get their status (status updates may possibly be done reverse to solve this section of the problem but not the run method).
Example 2: Agents create a collection of their "Intentions". Each Agent needs to iterate through its intentions and run/update/read intention status. Intentions also need to get information about the environment through Agent (if done directly through "World" it will create complex circles again) and also info of the Agent itself.
Below diagram shows a sub-set of classes, and some of their methods and properties:
I'm not seeing how forward declarations are not working for you. It looks like you need something like:
World.h:
#ifndef World_h
#define World_h
class Agent;
class World
{
World();
void AddAgent(Agent* agent) { agents.push_back(agent); }
void RunAgents();
private:
std::vector<Agent*> agents;
};
#endif
Agent.h:
#ifndef Agent_h
#define Agent_h
class World;
class Intention;
class Agent
{
Agent(World& world_): world(world_) { world.AddAgent(this); }
status_t Run();
private:
World& world;
std::vector<Intention*> intentions;
};
#endif
World.cc:
#include "World.h"
#include "Agent.h"
void World::RunAgents()
{
for(std::vector<Agent*>::iterator i = agents.begin(); i != agents.end; ++i)
{
Agent& agent(**i);
status_t stat = agent.Run();
// do something with stat.
}
}
// ...
Agent.cc:
#include "Agent.h"
#include "World.h"
#include "Intention.h"
// ...
You can solve the problem with only forward declarations, but you probably didn't separate the implementation from the declaration of the class.
If you need to call methods from the class, a full type is needed, which is why you need to include the file. You can include the file in a cpp (implementation file) without worrying about circular dependencies.

Hiding a class from outside when use is only for inside an API in C++

In languages like Java, you can declare a class without a modifier so it will only be visible inside the same package. I need to do something similar in C++. I am trying to create an API that will be a library to be used in other applications. After asking this question on programmers Stackexchange, I have decided to use some sort of handle, which will just be an unsigned integer that is passed to an API function, which will then pass it to a class that will look it up in some sort of table and return a pointer to the object the handle represents, back to the function. The API function will then be allowed to operate on the pointer, but without the public ever having access to the pointer.
The problem is, I would like the class that handles the handles to not be visible to the public (even though the public won't have an instance of the class that contains the handles), as it is only needed inside the API functions. Also, I wanted this handle class to be a template (only needed for compiling the API), because I would most likely have handles representing different types of classes (although I could probably get away with one table containing void pointers, but it seems a little unsafe). I cant hide the class in a .cpp file, because it would be needed in multiple .cpp files that compose the API.
Also, I was thinking about using the pimpl idiom in any classes that have public functions, that way if there were any private functions in them that needed a parameter related to one of my classes hidden from the public, a header file including hidden classes would not need to be included with the API libraries for the API user to be able to compile the program.
So what would be the best way to hide classes that are only needed among other classes (spread across multiple .h and .cpp files) inside the API its self, from the outside world?
You can indeed use the PIMPL idiom; just write a forward declaration of the type and use a (smart) pointer to it as a member. That should take care of header files.
For the implementation, just have a separate header file that is included by the implementation of the library but not by any part of the interface. Example:
// Interface.h
class Secret;
class Hi {
public:
Hi();
~Hi();
void stuff();
private:
Secret* secret;
};
// Implementation.cpp
#include "Secret.h"
#include "Interface.h"
Hi::Hi() : secret(new Secret) { }
Hi::~Hi() { delete secret; }
void Hi::stuff() { secret->stuff(); }
// Secret.h
class Secret {
public:
int data;
void stuff() { ... }
};
You don't have to hide it specifically, just don't include the internal header in the .h files that define your API.
It is perfectly normal for a project to have internal helper classes and functions that are not part of the external interface. Compile them into your library, but don't distribute the headers.
This is probably not the best solution, especially if you need to use the class in multiple classes without a common ancestor, but you could use a private or protected nested class:
class Foo {
protected:
class SecretClass {
// ...
};
// ...
};