2017-05-16 6 views
0

ストアオブジェクトとサーブのインターフェイスは、私はCsoundファイル自家製クラスを扱うと私はCsoundファイルを作成することができCSoundEngine、とそのインスタンスを処理しています(私のCSoundEngineに格納されている)を返し、そのポインタを返します。OOP - 私は現在、C++のプロジェクトに取り組んでいます

実際には、設計目的でインターフェイスへのポインタを返すようにしたいと思います。実際のオブジェクトをベクトルなどに格納し、C++(またはJava)のインタフェースを介して提供することは可能ですか?

答えが "はい"の場合、子クラスに応じて拡張して特定のインターフェイスを返すことができる汎用オブジェクトをベクターに格納できますか?

ありがとうございます!私が正しくあなたを理解していれば

+0

なぜ2つの異なる言語について質問していますか?それはあなたの質問を広すぎます。あなたが最も関心のないものを削除してください。 –

+0

私はあなたの質問の第2部分を理解していません。どうか明らかにしてください。 –

+0

この質問はちょっと危険に似ています...あなたは抽象基本クラスがどのようなものに使われているのか尋ねていますか?コードを作成して、意味のある例で何をしようとしているのかを示している方が良いでしょう。 – luk32

答えて

0

ので、あなたのような何かを持っている:

class CSound { 
    // Whatever 
}; 

class CSoundEngine { 
    // A lot of stuff 
    CSound* createSound(/* ... */); 
}; 

をそして、あなたはCsoundファイルが返されたくないが、インタフェースは、それは内部でのベクトルに格納されているが、特定のタイプです?

をあなたのインターフェイスを作成し、それらから派生: - インターフェース - まあ、最初の問題

は解決するのは簡単です。

class ISound { 
    public: 
     ISound(const ISound&)    = delete; 
     ISound(ISound&&)     = delete; 
     ISound& operator =(const ISound&) = delete; 
     ISound& operator =(ISound&&)  = delete; 

     virtual ~ISound() = default; 

     // Your ISound public API here as pure virtual methods, e.g.: 
     virtual const std::string name() const = 0; 
    protected: 
     ISound() = default; 
}; 

class ILoopable { 
    public: 
     ILoopable(const ILoopable&)    = delete; 
     ILoopable(ILoopable&&)     = delete; 
     ILoopable& operator =(const ILoopable&) = delete; 
     ILoopable& operator =(ILoopable&&)  = delete; 

     virtual ~ILoopable() = default; 

     // Your ILoopable public API here as pure virtual methods, e.g.: 
     virtual const bool isLoopingActive()  const = 0; 
     virtual  bool setLoopingActive(bool)  = 0; 
    protected: 
     ILoopable() = default; 
}; 

class CDefaultSound 
    : public ISound { 
    public: 
     CDefaultSound() = default; 

     // ISound implementation 
     inline const std::string name() const { return mName; } 

    private: 
     std::string mName; 
}; 


class CLoopableSound 
    : public ISound, 
     public ILoopable { 
    public: 
     CLoopableSound() 
      : ISound(), 
       ILoopable(), 
       mLoopingActive(true), 
       mName("") 
     { 
     } 


     // ISound implementation 
     inline const std::string name() const { return (mName + "(Loopable)"); } 

     // ILoopable implementation 
     inline const bool isLoopingActive() const { return mLoopingActive; } 
     inline bool setLoopingActive(bool active) { mLoopingActive = active; } 

    private: 
     bool  mLoopingActive; 
     std::string mName; 
}; 

int main() 
{ 
    // Now you can do something like this, for example, using polymorphism 
    // in your CSoundEngine (see below)... 
    ISound *pDef  = new CDefaultSound(); 
    ISound *pLoopable = new CLoopableSound(); 
} 

あなたは大丈夫ですISound由来のみCsoundファイルを使用する場合は、複数のクラスを必要としないが、その後、私はインターフェイスを使用してのポイントを理解していません。 重要:純粋な仮想インターフェイスメソッドのため、インターフェイスクラスをインストールすることはできませんので、shared_ptrやunique_ptrのようなポインタやRAIIポインタを使用する必要があります(RAIIをお勧めします...)

問題は - 特定の型をベクトルに格納することは、単一のベクタをforeachで許可する必要があるため、はるかに難しくなります。 OR!インターフェイスインスタンスを格納し、インターフェイスメソッドのみを使用します。

class DefaultSoundCreator { 
    static ISound* createSound(/* Criteria */) { ... } 
}; 

template <typename TSoundCreator> 
class CSoundEngine { 
    public: 
     CSoundEngine() 
      : mSoundCreator() { 
     } 

     std::shared_ptr<ISound> createSound(/* some criteria */); 

    private: 
     std::vector<std::shared_ptr<ISound>> mSounds; 
}; 

// cpp 
std::shared_ptr<ISound> CSoundEngine::createSound(/* some criteria */) { 
    // Use criteria to create specific sound classes and store them in the mSOunds vector. 
    ISound *pSound = TSoundCreator::createSound(/* forward criteria for creation */); 
    std::shared_ptr<ISound> pSoundPtr = std::shared_ptr<ISound>(pSound); 

    mSounds.push_back(pSoundPtr); 

    return pSoundPtr; 
} 

int main() { 
    std::unique_ptr<CSoundEngine<DefaultSoundCreator>> pEngine = std::make_shared<CSoundEngine<DefaultSoundCreator>>(); 

    std::shared_ptr<ISound> pSound = pEngine->createSound(/* Criteria */); 
} 

あなたはISoundによって提供される機能に頼ることができる。この方法ではなく、クリエーター・クラスを指定することにより、あなたは一般的なサウンド・エンジンを搭載したサウンド作成を制御できます。

インターフェイスベースクラスを使用した実際のタイプ消去の問題:インデックス2でCLoopableSoundを保存していたが、サウンドエンジンのメソッドcreateSound()によってのみISound-Interfacemethodsを使用できることがわかった:std :: shared_ptr ;

どのようにILoopableビヘイビアにアクセスしますか?

そしてこれは、それは哲学的になる点、である...私は読書をお勧めします:私が使用したい

https://akrzemi1.wordpress.com/2013/11/18/type-erasure-part-i/ Type erasure techniques https://aherrmann.github.io/programming/2014/10/19/type-erasure-with-merged-concepts/

一つの技術:

class CLoopableSound 
    : public ISound { 
    // All the above declarations and definitions 
    // AND: 
    static std::shared_ptr<CLoopableSound> fromISound(const std::shared_ptr<ISound>& other, bool *pSuccess = nullptr) { 
     std::shared_ptr<CLoopableSound> p = std::static_pointer_cast<CLoopableSound>(other); 
     if(pSuccess) 
      *pSuccess = p.operator bool(); 

     return p; 
    } 
}; 

// Use like 
std::shared_ptr<CLoopableSound> pLoopable = CLoopableSound::fromISound(pSoundEngine->getSound(...)); 
if(pLoopable) { 
    // Use 
} 

最後にもちろん、fromISound関数にテンプレートを作成し、キャストを使用してCLoopableSoundなどの代わりにILoopableにのみアクセスすることもできます。

関連する問題