私は異なるプラットフォーム上で自分のコードを実行できるように抽象レイヤーを作成しようとしています。私は最終的にハイレベルのコードで使用する二つのクラスのための例を挙げてみましょう:デザインパターン:C++抽象レイヤー
class Thread
{
public:
Thread();
virtual ~Thread();
void start();
void stop();
virtual void callback() = 0;
};
class Display
{
public:
static void drawText(const char* text);
};
私の悩みはある:どのようなデザインパターンは、私が実装における低レベルのコードの塗りをさせるために使用することができますか? は、ここに私のthoughsあると私は考えていないなぜ彼らは優れたソリューションです。理論的には
lowLevel/platformA/thread.cpp
に座っhighLevel/thread.h
における上記の定義に座ると、プラットフォーム固有の実装を持つには問題はありません。これは、リンク時に解決される低オーバーヘッドのソリューションです。唯一の問題は、低レベル実装ではメンバ変数やメンバ関数を追加できないということです。これにより、実装が不可能な特定のものが作成されます。アウト方法が定義(基本的にPIMPL-イディオム)にこれを追加することです:
class Thread { // ... private: void* impl_data; }
今、低レベルのコードは、それがvoidポインタに保存されている独自の構造体またはオブジェクトだことができます。ここで問題となるのは、プログラムを読むのが面倒で痛いということです。
私は
class Thread
を純粋仮想とし、それを継承して低レベルの機能を実装することができます。ハイレベルのコードは次のようにファクトリ関数を呼び出すことによって、低レベルの実装にアクセスできます。// 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(); }
これは十分に整頓だろうが、それは、静的なクラスのために失敗しました。私の抽象化レイヤーはハードウェアとIOのために使用されますが、私は実際に
Display
クラスへのポインタを持ち歩く代わりにDisplay::drawText(...)
を持つことができるようにしたいと考えています。もう1つの選択肢は、このようなリンク時に解決できるCスタイルの関数だけを使用することです。
extern "C" handle_t createThread()
。これは、ディスプレイのように1度しかない低レベルのハードウェアにアクセスするのは簡単で素晴らしいです。しかし、ロック(スレッド、スレッド、メモリ管理)を何度も行うことができる何かのために、私は醜い高レベルのコードでハンドルを持ち歩かなければならないか、ハンドルを隠す高水準のラッパークラスを持っています。どちらの方法でも、高レベルと低レベルの両方のそれぞれの機能にハンドルを関連付ける必要があるというオーバーヘッドがあります。私の最後の考えはハイブリッド構造です。純粋なCスタイルの
extern "C"
は、1度しか存在しない低レベルのもののために機能します。複数回あることができるもののためのファクトリ関数(3.を参照)。しかし、私は何かハイブリッドが一貫性のない、判読不能なコードにつながるのではないかと心配しています。
私の要件に合ったパターンを設計するためのヒントには非常に感謝しています。
はまだあなたの全体の質問を読んでいない:
また、私はクラスの継承の階層を作成する傾向があり、一部の人々は、この反対助言することを、予めご了承ください。しかし、C++には、C++ 11以降の抽象化レイヤーがあります。 – StoryTeller
私はFreeRTOSで埋め込まれたターゲットに取り組んでいます。もう1つのプラットフォームは、高水準コードの開発を容易にするコンピュータベースのエミュレーションです。私はC++ 11がこのシナリオをサポートしているとは思わない。 – LoveDaOOP