3

質問 1> 次のコードが機能しないのはなぜですか?

Question2> 正しい設計方法は?

#include <iostream>
#include <vector>
#include "boost/shared_ptr.hpp"

using namespace std;

class BaseClass
{};

class SubClass : public BaseClass
{};

int main()
{
    std::vector<boost::shared_ptr<SubClass> > vecSubClassShared;

    boost::shared_ptr<SubClass> sub1(new SubClass);

    vecSubClassShared.push_back(sub1);

    // Error    1   error C2440: 'initializing' : cannot convert from 'std::vector<_Ty>' to 'const std::vector<_Ty> &`
    const std::vector<boost::shared_ptr<BaseClass> >& vecBaseShared = vecSubClassShared;
}
4

2 に答える 2

4

C ++コンパイラの観点では、shared_ptr<BaseClass>shared_ptr<DerivedClass>異なる、無関係のタイプです。Derived*コンパイラーは、通常のポインターをからに変換できることを知っていますが、「スマートポインター」がポインターに似ていることを知らないためBase*、概念的に同じことがsに適用されることを知りません。shared_ptr

同じことがベクトルまたは一般的なテンプレートにも当てはまります。テンプレートの2つのインスタンス化は、2つの異なるクラスであり、それらの間に関係はありません(明示的に設計されていない場合)。したがって、コンパイラは、関連する型ではないvector<Something>への参照へのバインドを確認するvector<SomethingElse>ため、参照のバインドは失敗します。

しかし、タイプが何らかの形で関連している場合でも、バインディングは失敗します。

long l = 5;
int& ir = l; //ERROR
于 2013-02-27T08:17:49.777 に答える
1

shared_ptr<BaseClass>shared_ptr<SubClass>は別個の無関係な型であるため、オブジェクトのレイアウトが同じであるという保証がないため、一方のベクトルが他方のベクトルをエイリアスする方法はありません。

これは、たとえばconst std::vector<boost::shared_ptr<BaseClass> >&関数に渡すには、目的のタイプの一時的なベクトルを構築する必要があることを意味します。ただし、共有ポインターのエイリアシングを使用して、共有ポインターの参照カウントをインクリメントせずにこれを行うことができます。

#include <vector>
#include <memory>

struct B {};
struct D: public B {};

template<typename T, typename U>
std::vector<std::shared_ptr<T>> shared_vector_static_cast(
   const std::vector<std::shared_ptr<U>> &v)
{
   std::vector<std::shared_ptr<T>> w;
   for (const std::shared_ptr<U> &p: v)
      w.push_back(std::shared_ptr<T>(std::shared_ptr<void>(), p.get()));
   return w;
}

int main() {
    std::vector<std::shared_ptr<D>> v{std::make_shared<D>()};
    const std::vector<std::shared_ptr<B>> &w = shared_vector_static_cast<B>(v);
}
于 2013-02-27T08:48:13.733 に答える