2016-12-25 22 views
0

A(抽象基本クラス)を継承する4つのクラスB,C,D,Eがあるとします。 また、内容が B,C,D,Eのオブジェクトを指すA*のコンテナ(std::vector)があります。 ここにいくつかの規則があります: BオブジェクトとCオブジェクトが対話する場合、それらはベクトルから取り除かれ、代わりにDオブジェクトが作成されます。多態性とC++でのオブジェクト型の取得

また、C + D = E

は今、私がランダムに言ったベクトルの内容のいずれかを選択したとします。相互作用の仕組みを実装するためにどのオブジェクトがどのタイプであるかを知ることはどうすればよいでしょうか?

注:typeid演算子、動的キャストまたはフラグは使用しません。その他のソリューション?ここで

は、いくつかのコード

#include <iostream> 

class A { 
protected: 
    int v; 
public: 
    A(){} 
    ~A(){} 
}; 

class B :public A { 
public: 
    B(){} 
    ~B(){} 
}; 

class C : public A { 
public: 
    C(){} 
    ~C(){} 
}; 

class D : public A { 
public: 
    D(){} 
    ~D(){} 
}; 

class E : public A { 
public: 
    E(){} 
    ~E(){} 
}; 

int main() 
{ 
    std::vector<A*> container; 
    return 0; 
} 

どのように相互作用機能(複数可)を実装しているのですか?

+2

を行うには、仮想関数を使用することができ、([、最小完全、かつ検証例]を作成してみてくださいhttp://stackoverflow.com/help/mcve)をご覧ください。 –

+4

* "interact"とは何ですか?そして、あなたが知っているアイテムの位置は、それらが "相互作用する" *ときにどのように取り除かれるのですか? – StoryTeller

+2

「get object type」に関しては、特にC++では実行時のオーバーヘッドが発生します。仮想関数を使用して異なるクラスの動作を異なる方法で処理する設計は、通常、実行する方法です。 –

答えて

0

あなたが代わりにいくつかのコードを記述し、複数の派遣

struct B; 
struct C; 
struct D; 
struct E; 

struct A 
{ 
    virtual ~A() = default; 

    virtual std::unique_ptr<A> interactWithA(const A&) const = 0; 

//protected: 
    virtual std::unique_ptr<A> interactWithB(const B&) const = 0; 
    virtual std::unique_ptr<A> interactWithC(const C&) const = 0; 
    virtual std::unique_ptr<A> interactWithD(const D&) const = 0; 
    virtual std::unique_ptr<A> interactWithE(const E&) const = 0; 
}; 

// Your interact rules 

template <typename LHS, typename RHS> 
std::unique_ptr<A> interact(const LHS&, const RHS&) { return nullptr; } 

// Note that definitions and declarations must be split in reality 
// to be able to compile it 
std::unique_ptr<A> interact(const B&, const C&) { return std::make_unique<D>(); } 
std::unique_ptr<A> interact(const C&, const D&) { return std::make_unique<E>(); } 
// Maybe the reflexive case, C/B D/C ? 


// The derived classes 
struct B : A 
{ 
    std::unique_ptr<A> interactWithA(const A& a) const override { return a.interactWithB(*this); } 

    // Even if code look similar for other inherited class 
    // the difference is in the runtime type of the objects are known. 
    std::unique_ptr<A> interactWithB(const B& rhs) const override { return interact(rhs, *this); } 
    std::unique_ptr<A> interactWithC(const C& rhs) const override { return interact(rhs, *this); } 
    std::unique_ptr<A> interactWithD(const D& rhs) const override { return interact(rhs, *this); } 
    std::unique_ptr<A> interactWithE(const E& rhs) const override { return interact(rhs, *this); } 
}; 

struct C : A 
{ 
    std::unique_ptr<A> interactWithA(const A& a) const override { return a.interactWithC(*this); } 
    std::unique_ptr<A> interactWithB(const B& rhs) const override { return interact(rhs, *this); } 
    std::unique_ptr<A> interactWithC(const C& rhs) const override { return interact(rhs, *this); } 
    std::unique_ptr<A> interactWithD(const D& rhs) const override { return interact(rhs, *this); } 
    std::unique_ptr<A> interactWithE(const E& rhs) const override { return interact(rhs, *this); } 
}; 

struct D : A 
{ 
    std::unique_ptr<A> interactWithA(const A& a) const override { return a.interactWithD(*this); } 
    std::unique_ptr<A> interactWithB(const B& rhs) const override { return interact(rhs, *this); } 
    std::unique_ptr<A> interactWithC(const C& rhs) const override { return interact(rhs, *this); } 
    std::unique_ptr<A> interactWithD(const D& rhs) const override { return interact(rhs, *this); } 
    std::unique_ptr<A> interactWithE(const E& rhs) const override { return interact(rhs, *this); } 
}; 

struct E : A 
{ 
    std::unique_ptr<A> interactWithA(const A& a) const override { return a.interactWithE(*this); } 
    std::unique_ptr<A> interactWithB(const B& rhs) const override { return interact(rhs, *this); } 
    std::unique_ptr<A> interactWithC(const C& rhs) const override { return interact(rhs, *this); } 
    std::unique_ptr<A> interactWithD(const D& rhs) const override { return interact(rhs, *this); } 
    std::unique_ptr<A> interactWithE(const E& rhs) const override { return interact(rhs, *this); } 
}; 

、その後

std::vector<std::unique_ptr<A>> v /* = .. */; 

auto a = v[i]->interactWithA(*v[j]); 
if (a) { 
    // Remove v[i] and v[j] 
    // Insert a 
} 
1

あなたの問題は、抽象性が悪いと思われます。実際にあなたは正しい問題を解決していません。 正確なオブジェクトの型を知る必要はなく、代わりにランタイムポリモーフィズムに依存する場合は、継承を使用する必要があります。

いくつかのフラグでは、仮想関数のように各タイプのIDを返すことができますが、解決策ではなく解決策ではあります。それは間違っていることも簡単です。

class A 
{ 
    ... 
    virtual int get_id() = 0; 
} 

代わりに多型の変異体

、種類が固定されている場合(例えば、あなたが追加したり、クラスを削除する予定がない)、あなたはstd::variant<>(C++ 17)またはブーストを使用することができます。バリアント。それと対話するには、訪問者を使用し、std::visit()に電話する必要があります。それと対話するのは難しいかもしれませんが、私の意見では、あなたが説明した問題の解決策として、より適しています。

+0

別の方法がありますか? 1つのフラグやstd :: variantの必要はありません? –

+1

@JohnLannister、あなたは何も述べていません。私はあなたに "私は今チョコレートを食べています。私が食べているチョコレートは何ですか?"と書くことができます。 ABCDEは意味をなさない。問題のあなたの説明もありません – Incomputable