这段代码安全吗?将std :: vector <derived *>强制转换为std :: vector <base *> </base *> </derived *>

时间:2013-02-05 21:45:09

标签: c++ inheritance casting

基本上我有class Aclass 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 个答案:

答案 0 :(得分:3)

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

您应该从头开始使用std::shared_ptr<A>的向量,并使用指向B类型的对象的指针对其进行初始化。

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

答案 1 :(得分:3)

不要那样做。

考虑到({指针)B的向量不是(指向)A的向量,或者更确切地说,不是(指针)向量的普遍有效替换to)A;因此,有充分的理由说明你无法进行这样的转换。

虽然B向量中的所有内容确实是一组对象(也是A的实例),但请考虑以下算法:

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

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

此处的解决方案是使仅接受vector<A>灵活性的代码也可以在vector<B>上使用。换句话说,您需要将其设为模板。例如,您的模板只能接受从A派生的类型的向量作为参数。使用某些SFINAE技术和类型特征(例如std::is_base_of

)可以很容易地执行此操作

答案 2 :(得分:2)

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

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

答案 3 :(得分:2)

您仍然可以投射元素:

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

给你你想要的东西。

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

  • 使用shared_ptr<A*[]>代替shared_ptr<vector<A*>>(它可以按照您的意愿运作)
  • A**作为参数(并使用vector_b->data ()):它不会将您绑定到共享指针。
  • 更好:采用解除引用作为A的[智能]指针的方法(回想一下operator->链)
  • 使用std::vector<std::shared_ptr<A>>(废物资源)