2013-02-19 17 views
5
class Interface 
{ 
}; 

class Class : public Interface 
{ 
}; 

class Foo 
{ 
public: 
    std::vector<std::shared_ptr<Interface>>& GetInterfaces() 
    { 
     return *(std::vector<std::shared_ptr<Interface>>*)(&m_data); 
     //return m_data; 
    } 

private: 
    std::vector<std::shared_ptr<Class>> m_data; 
}; 

これは動作しますが、醜く怖いです。 より良い/より安全な方法がありますか?モジュールFooが属しているので、私はClass年代、Interface(およびFoo::GetInterfaces())のみInterface機能について知っておくべき別のモジュールと対話するために実装されていて、完全に機能タイプstd::vector<std::shared_ptr<Interface>>m_dataを作成する必要はありません。派生クラスのshared_ptrsのベクトルを基底クラスのshare_ptrsのベクトルにキャストする方法

ここに何か不明な点がある場合は、私には意味がありますが、私はしばらくの間問題に頭を抱えています。

答えて

7

キャストは正しくありません。キャストは正しくありません。私はあなたが未定義の振る舞いを呼び出すのはかなり確信しています。

新しいベクターを構築し、それを値で返す必要があります。

std::vector<std::shared_ptr<Interface>> b (m_data.begin(), m_data.end()); 
return b; 

これはまだかなり安い(1割り当て)。

+0

そのような状況で何をするつもり共有ポインタは何ですか?私は共有ポインタの2つの異なるタイプ間でポインタを共有したいと思っているのか分かりません! –

+0

@MichaelKohneいいえこれは大丈夫です。 – 111111

+0

ああ、勝利のセマンティクスを移動!値で返さなければなりません。 –

4

これは、vectorの実装では不可能ですが、参照は変換されないという問題もあります。あなたのコードはさらに悪く、未定義の動作です。

できることは、コンテナ自体の代わりに範囲またはbegin/endを公開するインターフェイスを提供することです。変換を行うtransform_iteratorと組み合わせる場合は、設定する必要があります。

サンプルコード:

class Interface { 
    virtual ~Interface(); 
}; 

class X : public Interface {}; 

class C { 

private: 
    typedef std::shared_ptr<Interface> iptr_type; 
    typedef std::shared_ptr<Class> ptr_type; 
    std::vector<ptr_type> v_; 

    struct F { 
    iptr_type 
    operator()(ptr_type p) { return iptr_type(p); } 
    }; 

    typedef boost::transform_iterator< 
    F, std::vector<ptr_type>::iterator> iiterator; 

public: 
    iiterator 
    begin() 
    { 
    return boost::make_transform_iterator(
     begin(v_), F()); 
    } 

    iiterator 
    end() 
    { 
    return boost::make_transform_iterator(
     end(v_), F()); 
    } 
}; 
+0

あなたのユースケースで意味をなさないなら、 .begin() 'と' .end() 'イテレータインタフェースは良いオプションです。 – 111111

+0

@ 111111確かに、それも。しかし、私は範囲がよりヒップなことだと思います。 – pmr

+0

私のコメントは、あなたの考えをサポートするものでした:) – 111111

関連する問題