2016-04-30 20 views
0

クロスプラットフォームのマルチスレッドアプリケーションを作成する際には、状況を考慮してください。クロスプラットフォームコードで抽象クラスのインスタンスを使用

これを実行すると、おそらくプラットフォームの機能をいくつかのクラスに分けることになります。たとえば、アプリケーションにテキストを出力するには、単純なコンソールが必要です。可能な方法は、いくつかの抽象クラスConsoleを宣言することです。これは、あるプラットフォームでそれを必要とするときに継承し、派生クラスのインスタンスを使用します。

Consoleインスタンスがどこかに必要であることが分かるまで(たとえば、クラスメンバーとして)すべてが問題ありません。他のクラスでクラスConsoleのメンバ変数を宣言しようとすると、抽象クラスのインスタンスが許可されていないため、エラーが発生することになります。しかし、コンパイル時に、派生クラスが実装され、正しいことが考えられますが、そのクラスの名前がわからない場合や、プラットフォームによって異なる名前がある場合もあります。

ここは複雑な例です。

クロスプラットフォームのマルチスレッドアプリケーションを開発する場合は、Syncer(シンクロナイザー)のようなものが必要です。それのアナログはWindows APIのmutexオブジェクトです。

プラットフォームによっては、クラスが異なることがわかります。しかし、プラットフォームの変種にはいくつかの方法があることは知っています。例えば、これらの方法はlockunlockです。あなたは、これらのメソッドが実行されるのか分からないので、あなたは次のように純粋仮想それらを宣言します。

class Syncer 
{ 
public: 
    virtual void lock()=0; 
    virtual void unlock()=0; 
} 

そして今、いくつかのクラスを開発し、あなたがものをする必要はないことを、実感が、このSyncerの多く-s。しかし、クラスは抽象クラスなので、それを行うことはできません。

私が見つけた可能な解決策は以下のとおりです。

1)は、テンプレートを使用してください。たとえば:

template<class syncer> 
class SyncUser 
{ 
public: 
    syncer syncInstance; 
    SyncUser() 
    { 
     syncInstance().lock; 
} 

しかし、問題は、クラスのユーザーがsyncerパラメータの代わりに他のクラスを貼り付けることである(彼はあるいは、問題ではないではないだろうだろう。彼はこれを行うことができます。)。。そのソリューションは、一般的なソリューションが期待されるほど良くはありません。

2)マクロを使用します。この方法を使用している場合、Syncer.hの内容は、次のようになる:"platform1_sync_implement.h"ファイルには、次のを持っている場合

class Syncer 
{ 
public: 
    virtual void lock()=0; 
    virtual void unlock()=0; 
} 
#ifdef PLATFORM1 
#include "platform1_sync_implement.h" 
#else 
#include "platform2_sync_implement.h" 
#endif 

:今

#include "Syncer.h" 

class SyncPlatform1 : public Syncer 
{ 
    //Correct implementation 
} 

#define Syncer SyncPlatform1 

、誰もがSyncer.hを含ま実装したバージョンを持っているでしょう。 しかし、この方法は、また、Sync抽象化が実装されるプラットフォームのリストを必要とするので、良くありません。大きなプロジェクトではそれほど良いことではありません。クラスを宣言し、他のプログラマーがそれを使うことができるかどうかを気にするだけです。

したがって、問題は、抽象クラスのインスタンスをどこかで実装することができるということを知っているということです。

P.S:それはそのような質問のための最良の名前ではないことを知っています。 P.P.S .:悪い英語を申し訳ありません。

+0

tl; dr。短い答えです "抽象クラスのインスタンス"はありません。定義では、抽象クラスはインスタンス化できません – user463035818

+3

私はあなたの動機付けによって確信していません。バーチャルファンクション多相は、実行時に異なる実装*を扱うためのものです。複数のプラットフォームをサポートするユースケースでは、実行時の決定がないようです。あなたのプログラムは、ゲームボーイとプレイステーションで同時に*実行されていません。むしろ、各プラットフォーム用に再コンパイルします。 –

+0

実際には、別のクラスのメンバとして抽象クラスから派生したオブジェクトが必要な場合は、その抽象クラスへのポインタをメンバとして持つことができます。 – user463035818

答えて

1

、あなたは多型を使用しないでください、あなたはむしろ古き良きの#if __linux__を使用する必要があり、& &定義さ__darwin__ __mac__定義されたの#if、_WIN32の#ifなど

あなたが必要な場合実際のCPUを最大限に活用するには、最終的にプログラムが実行され、実行可能なCPUごとに特別に最適化された実装が必要な場合は、最適な実装を選択するための実行時メカニズムが必要なため、別の話です。

0

抽象クラスの背後にあるアイデアは、基本クラスを完成させるためのポイントを提供することですが、将来は基本クラスのユーザーによって提供されます。

これが目的の場合は、抽象クラスを使用してください。基底クラスが使用可能であるべき場合として-され、本当にルーチンはありませんし、まだ使用してクラスで必要とされないかは重要ではありません場合は、空のルーチン

class BASE { 
public: 
    void SomethingUnusedHere() {} 
}; 

ユーザーが同じことを行うことができます。

class BASE { 
    : 
    void Func() = 0; 
    : 

} 

class CHILD : public BASE { 
    : 
    void Func() {} 
    : 
} 

もちろん、Funcが本当に必要な場合は適切なコードを含める必要があります。異なるプラットフォーム上の異なる実装を持つように

+0

問題は、私は基本クラスの宣言しか持っていませんが、子クラスを使うべきです。あなたの例を使用している場合は、 'CHILD'コンストラクタをどこかで呼び出す必要があります。メンバ変数として' BASE'を使用すると不可能です。 –

+0

いいえ、私は、子クラスも空の関数を実装できることを暗示しました。私はそれの例を含めるように編集します。 – DAV

関連する問題