Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将基本类型为派生类型的STL容器强制转换为派生类型可以吗?_C++_Stl_Vector_Polymorphism - Fatal编程技术网

C++ 将基本类型为派生类型的STL容器强制转换为派生类型可以吗?

C++ 将基本类型为派生类型的STL容器强制转换为派生类型可以吗?,c++,stl,vector,polymorphism,C++,Stl,Vector,Polymorphism,将STL容器从基类型强制转换为派生类型可以吗? 例如,我有两个向量。第一个是基类类型,第二个是派生类类型 class Base { // Code }; class Derive : public Base { // Code }; 用法 vector*vec_base=新向量; //将一些派生类型数据添加到vec_库 向量*向量导出=(向量*)(向量基); //使用元素作为派生指针。很好。 这样行吗?(它工作得很好,但我想得到一些关于这方面的评论)。多谢各位 编辑:根据答案进行更新 比如

将STL容器从基类型强制转换为派生类型可以吗? 例如,我有两个向量。第一个是基类类型,第二个是派生类类型

class Base
{
// Code
};

class Derive : public Base
{
// Code
};
用法

vector*vec_base=新向量;
//将一些派生类型数据添加到vec_库
向量*向量导出=(向量*)(向量基);
//使用元素作为派生指针。很好。
这样行吗?(它工作得很好,但我想得到一些关于这方面的评论)。多谢各位

编辑:根据答案进行更新

比如说,如果我小心地使用该向量,并且不会与多重继承一起使用,也不会插入派生类型以外的对象,可以吗?(我想不是)


非常感谢你的回答

这绝对不行,这是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);
}
#包括
#包括
#包括
使用名称空间std;
阶级基础
{
//代码
虚拟~Base();
};
类驱动:公共基
{
//代码
};
数据驱动*转换(基本*英寸){
//在这里断言?
返回动态_-cast(in);
}
int main(){
vector*vec_base=新向量;
//将一些驱动类型数据添加到vec_base
向量*vec_derrive=新向量;
转换(vec_base->begin(),vec_base->end(),back_insert_迭代器(*vec_derrive),convert);
}

不,这样不行


假设我有从
Base
派生的
Derrive2
。我可以把它放在STL容器中,但它不能安全地强制转换到
Derrive

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

如果它现在起作用,那就认为你自己运气不好,它没有崩溃。
如果您知道向量中的所有项都是派生类,那么只需将向量指向前面的派生对象即可。如果您不知道,则强制转换是不安全的。

您正在执行c样式强制转换,这实际上是在执行
重新解释\u强制转换
,它告诉编译器“从现在开始,像对待y一样对待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
}
for(无符号整数i=0;ilength();i++)
{
Derrive*d=动态投影(向量基[i]);
如果(d){
//这个元素是一个Derrive实例,所以我们可以在这里将其视为一个实例
}
//否则,跳过它,记录错误,抛出异常等等,
//向量中的此元素不是Derrive类型
}

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

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

vector<Derived*> vector2 = *( reinterpret_cast< vector<Derived*>* >(&vector1) );
vector2=*(重新解释_cast(&vector1));
注:
我的回答是信息性的,请坚持使用std::transform方法。我不确定在STDC++实现中,除了GCC之外的其他实现中,向量的行为是否相同,也就是说,我不确定断言“list和list是否具有相同的内部结构"在其他实现中也是如此。

好吧,假设我会小心地使用该向量,不会将Derrived2类型放入向量。现在,它可以了吗?@Morpheus不,它不可以-向量类型仍然没有关联。我几乎+1@Morpheus感谢一分钟前我嘴里发出的笑声。这是一种很好的方式。非常感谢你,这是一个shame dynamic_cast不是一个函数,因为这样您可能根本不需要convert函数来包装dynamic_cast。当您使用vec_驱动程序时,请在使用它之前检查每个成员是否为null。如果任何dynamic_cast失败,您将在向量中获得null项。如果您确定所有元素实际上都是指向派生,您可以合法地将动态强制转换替换为静态强制转换,这样会更快。当然,如果不是这样,您的程序将显示未定义的行为。使用C++11中的lambda函数,我会尝试将强制转换移动到lambda函数中,以消除对
转换()的需要
function.Re:update-如果不使用诸如std::transform之类的工具,您所做的任何事情都不会使它使用除reinterpret\u cast之外的任何cast,这不是您要查看的内容for@awoodland所以,即使不是多晶型,重新解释铸型也是不好的?我的意思是,即使我100%确信“我知道确切的类型”在这种情况下,vector的reinterpret_cast是未定义的?reinterpret_cast在std::vector上肯定是不好的,问题是没有(可移植的,标准化的)理由来假设std::vector和std::vector的内存布局是兼容的,这样就可以工作了。@Tomalak更正了。感谢您指出…)@awoodland,两者都是指针,指针无论指向什么,其行为都相同,指针无论指向什么,其大小都相同。。。如果我们假设向量实现不是专门用于Base*或派生*,并且它不是侵入性的,那么解决方案会起作用……是的,应该是这样。但我不能让用户使用dynamic_cast,因为它处于关键路径。我认为,通过强制编译器强制转换为Derrive类型,它应该可以工作
vector<Derived*> vector2 = *( reinterpret_cast< vector<Derived*>* >(&vector1) );