是否可以将具有Base类型的STL容器转换为Derived类型?

时间:2011-03-28 14:21:55

标签: c++ stl vector polymorphism

将STL容器从Base类型转换为Derived类型是否可以? 例如,我有两个向量。第一个是Base类的类型,第二个是Derive类的类型。

class Base
{
// Code
};

class Derive : public Base
{
// Code
};

用法

    vector<Base*>*  vec_base = new vector<Base*>;

    // Add some Derive type data to vec_base

    vector<Derive*>* vec_derive = (vector<Derive*>*)(vec_base);

    // Using elements as Derive pointers. Works fine. 

这可以吗? (它工作正常,但我想得到一些关于此的评论)。非常感谢你。

编辑:根据答案进行更新。

说,如果我仔细使用该向量,并且不会使用多重继承并且不会插入除Derive类型之外的对象,那么它可以吗? (我猜,它不是)

非常感谢你的答案。

5 个答案:

答案 0 :(得分:9)

这绝对不行,并且是c样式转换屏蔽错误的示例之一。 “它适用于我”并不表示在这种情况下定义明确的行为。

如果你真的想这样做,我建议:

#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

class Base
{
// Code
virtual ~Base();
};

class Derrive : public Base
{
// Code
};

Derrive *convert(Base * in) {
   // assert here?
   return dynamic_cast<Derrive*>(in);
}

int main() {
    vector<Base*>*  vec_base = new vector<Base*>;

    // Add some Derrive type data to vec_base

    vector<Derrive*>* vec_derrive = new vector<Derrive*>;

    transform(vec_base->begin(), vec_base->end(), back_insert_iterator<vector<Derrive*> >(*vec_derrive), convert);
}

答案 1 :(得分:2)

你正在做一个c风格的演员表,它实际上正在做一个reinterpret_cast,它告诉编译器“从现在开始就像对待x一样,并且只相信我它有效”。所以它肯定会编译,但这是一个坏主意。这里没有类型安全,它可能在某些时候有效,但在其他时候会无法预测崩溃。

你能做什么呢?

for (unsigned int i=0; i < vec_base->length(); i++)
{
  Derrive* d = dynamic_cast<Derrive*> (vec_base[i]);
  if (d ) {
     // this element is a Derrive instance, so we can treat it like one here
  }
  // else, skip it, log an error, throw an exception, whatever,
  // this element in the vector is not of type Derrive
}

答案 2 :(得分:1)

这不行。具有不同T s的模板化类型是不相关的类型(即使它们都说std::vector,并且使用C风格的转换只会让您摆脱未定义的行为。

如果它现在似乎有效,请认为自己不幸运,它没有崩溃。

如果您知道向量中的所有项都是派生类,那么只需将向量指向前面的派生对象即可。如果你不知道,那么演员表是不安全的。

答案 3 :(得分:0)

没有。这不会很好。

说我Derrive2来自Base。我可以把它放在STL容器中,但它不会安全地转换为Derrive

答案 4 :(得分:0)

更安全的方法是使用std :: transform。

但是,因为在std :: list的实现中,T = Base *或T = Derived *的行为方式相同(两者都具有相同的大小),所以列表具有与列表相同的内部结构。因此可以执行以下技巧:

vector<Derived*> vector2 = *( reinterpret_cast< vector<Derived*>* >(&vector1) );

注意: 我的回答是信息性的,请坚持使用std :: transform方法。我不确定在STDC ++实现中,除了GCC以外,矢量的行为方式是否相同,即。我不确定断言“list&lt; Base *&gt;和list&lt; Derivated *&gt;具有相同的内部结构”是否适用于其他实现。