3

Question1> 为什么下面的代码不起作用?

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*to转换Base*,但它不知道在概念上同样适用于shared_ptrs,因为它不知道“智能指针”类似于指针。

这同样适用于向量或一般模板:模板的两个实例化是两个不同的类,它们之间没有关系(如果没有明确设计)。所以编译器看到一个vector<Something>对 avector<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 回答