2

基本上我有一个class A和一个class B : public A

我想投一个std::shared_ptr<std::vector<A*>到一个std::shared_ptr<std::vector<B*>

问题是std::vector<B>不继承自std::vector<A>smart_ptr也不是。所以我做了一个可怕的演员

  std::shared_ptr<VectorA> vector_a = * ((std::shared_ptr<VectorA>*)&vector_b);

代码在那里编译并运行,但它安全吗? http://liveworkspace.org/code/3dQTz1$0

4

4 回答 4

3

这是一个可怕的解决方案。当您将一种类型的对象向量转换为另一种类型时,您可能会遇到各种不正确/未定义的行为。

您应该从一开始就使用 vector ofstd::shared_ptr<A>并用指向那里类型对象的指针初始化它们B

如果不可能,您可以创建一个新的矢量持有std::weak_ptr<A>以避免两次管理这些对象。

于 2013-02-05T21:51:35.543 回答
3

不要那样做。

考虑 (pointers to)B的向量不是(pointers to) 的向量A,或者更准确地说,不是 (pointers to) 向量的普遍有效替代A;因此,您不能执行这样的转换是有充分理由的。

虽然你在一个向量中拥有的B确实是一组对象,它们是(也是(的实例)A,请考虑以下算法:

void f(vector<A>& v)
{
    A a;
    v.push_back(a);
}

现在假设您f()使用 的向量调用B。那将是尝试将一个类的实例添加B到一个应该只包含 type 元素的集合中B

这里的解决方案是使只接受 a 的代码vector<A>足够灵活,也可以在vector<B>. 换句话说,您需要将其设为模板。例如,您的模板只能接受从A. 使用一些 SFINAE 技术和类型特征(例如std::is_base_of.

于 2013-02-05T21:51:46.723 回答
2

严格来说,取消引用操作应该成功。两个向量都是指针容器,因此将一个向量转换为另一个,虽然对于生产代码是不可接受的,但仍将使用相同的尺寸和对齐方式。

尽管 C++ 提供了丰富的抽象来避免这些恶作剧,但最好将派生对象的向量填充为指向基类的指针。

于 2013-02-05T21:52:01.663 回答
2

您仍然可以转换元素:

A* a = vector_b->at (42);

给你你想要的。

现在,如果您编写了shared_ptr<vector<A*>>作为参数的函数,那么您有多种解决方案可以让您摆脱这种情况:

  • 使用shared_ptr<A*[]>而不是shared_ptr<vector<A*>>(它可以按您的意愿工作)
  • 作为A**参数(并使用vector_b->data ()):它不会将您与共享指针联系起来。
  • 更好:将取消引用的迭代器作为 [smart] 指针A(回想一下operator->链)
  • 使用std::vector<std::shared_ptr<A>>(浪费资源)
于 2013-02-05T21:55:51.747 回答