2016-05-27 14 views
1

コピーできないオブジェクトを作成する際に問題があります。次の例を考えてみましょう:コピー可能なオブジェクト、マップ、shared_ptr:コピーコンストラクタのエラー

class Uncopyable{ 
protected: 
    Uncopyable(){}; 
    ~Uncopyable(){}; 

private: 
    Uncopyable(const Uncopyable&); 
    Uncopyable& operator=(const Uncopyable&); 
}; 


class Base { }; 
class Derived : public Base { }; 

class A : private Uncopyable { 
public: 
    A(std::map<std::string, std::shared_ptr<Base>> & inMap); 
private: 
    A(const A&); 
    A& operator=(const A&); 
}; 

int main() { 
    std::map<std::string, std::shared_ptr<Derived>> lMap; 
    std::shared_ptr<A> oA(std::make_shared<A>(lMap)); 
} 

私は、オブジェクトAは、非コピー可能であることを前提とした場合、それはwork.Asポインタをしない、私は、オブジェクトAが派生が基本であることを理解することが予想されるが、代わりにI次のメッセージが表示されます:

error C2664: 'A::A(const A &)' : cannot convert argument 1 from 'std::map<std::string,std::shared_ptr<Derived>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' to 'std::map<std::string,std::shared_ptr<Base>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>> &' 
1>   with 
1>   [ 
1>    _Kty=std::string 
1> ,   _Ty=std::shared_ptr<Derived> 
1>   ] 
1>   and 
1>   [ 
1>    _Kty=std::string 
1> ,   _Ty=std::shared_ptr<Base> 
1>   ] 

ありがとうございます。

答えて

3

エラーはAのコピー不可とは関係なく、実際にコピーコンストラクタにはありません。これはmapコンストラクタにあります。

std::map<std::string, std::shared_ptr<Derived>> 

タイプTの左辺値参照は左辺値だけで満足することができるである引数:エラーがA'コンストラクタが

std::map<std::string, std::shared_ptr<Base>> & 

を取り、あなたが渡しているという事実に関係していますTのタイプまたはT(またはoperator T&を有するタイプ)に由来するタイプのものである。しかし、std::map<std::string, std::shared_ptr<Derived>>は実際にはstd::map<std::string, std::shared_ptr<Base>>から継承されません。また、2つの型はまったく関係しません。std::mapのクロスタイプコンストラクタはありません。

つまり、DBであるということは、map<X, D>map<X, B>であることを意味するものではありません。このようにC++型システムには型の共分散はありません。いくつかのタイプは、少なくともあなたがClass<D>(例えばstd::shared_ptr)からClass<B>を構築することができますが、それは標準コンテナの真実ではない(例えばvectormap、...)

あなたはstd::shared_ptr<Base> Sを保持するためにlMapを変更する必要がありますこれが機能するためには内部的にはstd::shared_ptr<Derived>を保持できますが、mapの型は一致しなければなりません。


サイドノート、C++ 11の場合、Uncopyableは不要です。あなたはこれらの操作を明示的にdeleteと簡単にすることができます:

A(A const&) = delete; 
A& operator=(A const&) = delete; 
+0

私はあなたが指摘して参照してください、それは非常に明確です。 関数fが引数としてstd :: shared_ptr をとり、std :: map >マップを定義します。私はlMap [0]にstd :: shared_ptr を割り当てます。 lMap [0]をfに使用することはできません。 – Canardini

+0

@Canardini 'f'が' shared_ptr 'を受け取った場合、' shared_ptr 'をそれに渡すことはできません。実際に 'Derived'オブジェクトを指していることをどのように知っていますか? – Barry

+0

そうですね、これはあなたの答えから私が理解したものです。私は動的キャストポインタを使用しようとしましたが、問題を解決できませんでした。 – Canardini

関連する問題