C++ 将基本类型为派生类型的STL容器强制转换为派生类型可以吗?
将STL容器从基类型强制转换为派生类型可以吗? 例如,我有两个向量。第一个是基类类型,第二个是派生类类型C++ 将基本类型为派生类型的STL容器强制转换为派生类型可以吗?,c++,stl,vector,polymorphism,C++,Stl,Vector,Polymorphism,将STL容器从基类型强制转换为派生类型可以吗? 例如,我有两个向量。第一个是基类类型,第二个是派生类类型 class Base { // Code }; class Derive : public Base { // Code }; 用法 vector*vec_base=新向量; //将一些派生类型数据添加到vec_库 向量*向量导出=(向量*)(向量基); //使用元素作为派生指针。很好。 这样行吗?(它工作得很好,但我想得到一些关于这方面的评论)。多谢各位 编辑:根据答案进行更新 比如
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
派生
,您可以合法地将动态强制转换替换为静态强制转换,这样会更快。当然,如果不是这样,您的程序将显示未定义的行为。使用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) );