2017-01-04 7 views
-1

私はオブジェクトベースの同じクラスでいっぱいのベクトルを渡したいと思います。 std::reference_wrapperと参照なしの両方で修正されていません。 これを解決する正しい方法は何ですか?std :: vectorをパラメータに渡す正しい方法は何ですか?

class MyClass 
{ 
public: 
    MyClass(int){}; 
    virtual void print() const { 
     std::cout<<"MyClass"<<std::endl; 
    } 
}; 
class MySubClass : public MyClass 
{ 
public: 
    MySubClass(int a):MyClass(a){}; 
    virtual void print() const { 
     std::cout<<"MySubClass"<<std::endl; 
    } 
}; 
void test(const std::vector<std::reference_wrapper<MyClass>>& v) 
{ 
    for (const auto& c : v) { 
     c.get().print(); 
    } 
} 
void test(const std::vector<MyClass>& v) 
{ 
    for (const auto& c : v) { 
     c.print(); 
    } 
} 
int main() 
{ 
    { 
     MySubClass s(2); 
     std::vector<MyClass> v; 
     v.push_back(s); 
     test(v);//print MyClass, but I need MySubClass 
    } 
    { 
     MySubClass s(2); 
     std::vector<std::reference_wrapper<MyClass>> v; 
     v.push_back(s); 
     test(v);//print MySubClass 
     test({2}); 
     test({s});//wrong ambigious 
    } 
    return 0; 
} 
+2

'const std :: vector &v' - ベクターへの参照を渡すので、ここには「MyClass」のコピーはありません。 – Holt

+6

あなたはリンゴをバイクと比較しています - 参照のベクトルまたはオブジェクトのベクトルが欲しいですか?彼らは全く異なる用途を持っています。あなたは何をしようとしているのですか? –

+0

@Holt申し訳ありませんが、私は十分に明確にしていませんでした。今私は再編集した。 –

答えて

1
{ 
    MySubClass s(2); 
    std::vector<MyClass> v; 
    v.push_back(s); 
    test(v);//print MyClass, but I need MySubClass 
} 

ここでの問題は、あなたがMyClassのベクトルでMySubClassオブジェクトを格納しようとしているということです。 MySubClass全体を格納することはできません。代わりに、MyClass親サブオブジェクトのみが格納されます。これは、格納されたオブジェクトをあたかもMySubClassのインスタンスと同じように扱いたいという欲求と矛盾します。

{ 
    MySubClass s(2); 
    std::vector<std::reference_wrapper<MyClass>> v; 
    v.push_back(s); 

これは、以前の問題を解決します。参照は、静的型のサブクラスを参照できます。ただし、オブジェクトはベクトルに格納されません。オブジェクトはローカル変数sとして格納され、ベクトルによってのみ参照されます。

test(v);//print MySubClass 
    test({2}); 
    test({s});//wrong ambigious 

ここでの問題は、あなたがMySubClassを受け入れていないが、両方がMySubClassの初期化リストから初期化することができるものを受け入れるどちらもそのうち2つのオーバーロードを、持っているということです。したがって、過負荷の分解能は曖昧です。コンパイラは、どのオーバーロードを呼び出すか分からない。

明示的な初期化リストの代わりに明示的な一時的な初期化を使用してください。

test(std::vector<MyClass>{2}); 
    test(std::vector<std::reference_wrapper<MyClass>>{s}); 

または、オーバーロードは使用せず、一意の名前の関数を使用します。

+0

OPは 'std :: vector 'を考慮したいかもしれません。これは、reference_wrapperバージョンと非常によく似た動作をしますが、コードの読者にとっては概念的に簡単です。 –

+0

@MartinBonnerしかし、ポインタはこの便利な文法の 'test({2})'を失う可能性があります。 –

+0

@Ringo_D:そうです。その構文が便利な場合、ポインタはあまり魅力的ではありません。 (多くのアプリケーションではそうではありません)。 –

関連する問題