使用* void作为static_cast的缓冲区

时间:2012-08-06 15:37:25

标签: c++ void-pointers downcast

所以我去了:

class A;

class B : public A;

class C : public B;

vector<A*> *vecA;

vector<C*> *vecC;

我想把vectC投入vecA。

vector<A*> *_newA = static_cast< vector<A*>* >(vecC); //gives an error

所以我使用void指针作为缓冲区和强制转换:

void *buffer = vecC;

vector<A*> *_newA = static_cast< vector<A*>* >(buffer); //works

这有效吗?还有其他办法吗?

5 个答案:

答案 0 :(得分:4)

您应该只有std::vector<A*>,然后当您希望将BC放入其中时,您可以执行此操作:

 std::vector<A*> vec;
 vec.push_back(b);

这比你现在做的任何事都要好得多。

此外,您应该使用std::unique_ptrstd::shared_ptr,具体取决于指针的所有权语义。拥有原始指针是一个禁忌!!

答案 1 :(得分:3)

  

这有效吗?

不,不是。完全未定义如果访问它会发生什么。

  

还有其他办法吗?

是。这取决于你想做什么:

  1. 复制内容:std::copy(vecC.begin(), vecC.end(), std::back_inserter(vecA));

  2. 如果给定A*的容器或迭代器或任何其他派生类型

  3. ,则创建一个适用于C*的随机访问容器的适配器
  4. 我相信还有其他解决方案,只需告诉我们你想做什么

答案 2 :(得分:1)

我认为您正在寻找covariant对通用(模板)类型的支持。 C ++完全不支持这一点。 CLR - and C#/VB支持它 - 尽管只在最新版本中支持。

尽管如此,为了回应别人的反应,你可能会咆哮错误的树。我的预感是你想要一个指向A类对象的指针向量......这种类型应该包括虚方法和虚拟析构函数 - 如果需要的话。如果没有更好地理解你想要解决的高级问题,就不可能更具体地选择合适的替代方法 - 这在你的问题中并不明显。

答案 3 :(得分:1)

你可能需要知道的神奇词汇是“协方差”和“逆变”。看看here是否涉及一个非常密切相关的问题。

简短的回答:没有简洁明智的方法来做你想要仅使用演员表进行的转换。您需要将旧矢量的内容复制到新矢量中。

但更重要的是:1。不要在标准容器类型上使用new。 2.不要传递指向标准容器类型的指针。 3.不要将原始指针传递给您自己的对象,而是使用std::shared_ptr

答案 4 :(得分:1)

使用void*只需使用reinterpret_cast,而不是通过#include <iostream> #include <vector> using namespace std; class Base {}; class Derived: public Base { public: int x; Derived(): x(42) {} }; int main() { vector< Derived* > v; Derived d; v.push_back( &d ); cout << v.back()->x << endl; // 42 vector< Base* >* pbv = reinterpret_cast< vector< Base* >* >( &v ); Base b; pbv->push_back( &b ); cout << v.back()->x << endl; // indeterminate value } 绕道而行。

然而,您希望转换允许非常不正常的事情

T**

T const**转换为A时,问题大致相同(不允许,可以允许不正常的事情)。缺点是,除非你确切知道自己在做什么,否则不要这样做。它的时间越长,嗯,这里没有讨论它的余地,但它涉及区分可变和不可变的集合,并且非常小心。

<小时/> 编辑:正如其他人(没有解决转换问题)已经说过,实际的解决方案是{{1}}指针或智能指针的向量,然后使用C ++多态(即虚拟成员函数)。