2016-04-28 17 views
0

私はC++を学んでいます。私は基底クラスBaseとその派生クラスDerivedを持っています。そして彼らはpush_backstd::vector<Base*> vecに入れています。 vec[0] == &Basevec[1] == &Derivedと仮定すると、仮想機能なしでvec[0]vec[1]の機能を切り替えることができます。コードはこの質問の終わりです。仮想関数なしでそれを行うより良い方法はありますか?純粋なデータクラスが必要なので、非メンバ関数を追加してデータクラスのコードを変更しないようにしたい。どうもありがとうございました。あなたはそれが「基本」を必要とし、適切として「TYPE_」、または「int型(無効)」の代わり残念ながら、これはおそらく、あなたの質問に答えていないバーチャル機能なしで機能を切り替えるより良い方法はありますか?

void SwitchFunction(Base* ptr) 
{ 
    auto&& type = typeid(*ptr); 
    if (type == typeid(Base)) 
     Function(dynamic_cast<Base*>(ptr)); 
    else if (type == typeid(Derived)) 
     Function(dynamic_cast<Derived*>(ptr)); 
    else std::cout << "invalid type(=" << type.name() << ")" << std::endl; 
} 

「の型ID」を使用する必要はありません

class TypeInterface { 
public: 
    virtual int type(void) = 0; 
    virtual ~TypeInterface() {} 
}; 

class Base : public TypeInterface { 
public: 

    static constexpr int type_ = 1; 
    virtual int type(void) { 
     return type_; 
    } 

    virtual ~Base() {} 
}; 

class Derived : public Base { 
public: 

    static constexpr int type_ = 10; 
    virtual int type(void) { 
     return type_; 
    } 

    virtual ~Derived() {}; 
}; 

void Function(Base* ptr) { 
    std::cout << "function for Base" << std::endl; 
} 

void Function(Derived* ptr) { 
    std::cout << "function for Derived" << std::endl; 
} 

void SwitchFunction(int type, void* ptr) { 
    switch (type) { 
    case 1: { 
     Base* original_type_ptr = static_cast<Base*>(ptr); 
     Function(original_type_ptr); 
     break; 
    } 
    case 10: { 
     Derived* original_type_ptr = static_cast<Derived*>(ptr); 
     Function(original_type_ptr); 
     break; 
    } 
    default: 
     std::cout << "invalid type(=" << type << ")" << std::endl; 
    } 
} 

void test_function_selecter(void) { 

    Base b; 
    Derived d; 

    std::vector<Base*> vec; 

    vec.push_back(&b); 
    vec.push_back(&d); 

    for (auto e: vec) { 
     SwitchFunction(e->type(), e); 
    } 

} 
+1

コードには未定義の動作があります。それらはいくつかの厄介なキャストです。理想的には、C++を学んでいるときにポインタやキャストを使用しないでください。 –

+1

関数を変数として保存するのはどうですか?すべてのインスタンスで使用されている場合は静的にすることができます。 std :: function myFunc = [](void){//何か} – Striker

+0

ありがとう、Kerrek SB。私はあなたの懸念事項を見つけようとしました。タイプとボイドの組み合わせが間違っているかもしれないことを恐れるかもしれないと思います。私の場合、SwitchFunction(e-> type()、e)は固定形式です。だから私は間違った組み合わせを選ぶことを避けることができると思う – mora

答えて

1

仮想関数(デストラクタなど)。

+0

ありがとう、Issac。私はあなたに私のポイントを伝えることができなかったのですが、恐れています。要点は、データクラスを変更せずにデータクラスを処理する関数を追加したいと思うことです。仮想クラスを使用する場合は、データクラスに仮想関数を追加(および変更)する必要があります。だから仮想デストラクタは私のために大丈夫です。もう一度あなたのソリューションをありがとう。しかしもう少しお聞かせください。スピードパフォーマンスの観点から、あなたの方法または私の方法はどちらが良いか、同じですか? – mora

+1

&それ以上のものはおそらくほぼ同じですが、実際に気にかけてみると、私はそれをテストすることを提案したいと思います。個人的には、あなたのタイプの数が本当に多い場合を除き、私は気にしません。 'if/else if'ステートメント( 'typeid'で 'switch'を使うことはできません)はもちろん、私のソリューションはオブジェクトのスペースをほとんど占有しません。 – Isaac

関連する問題