简体   繁体   English

使用* void作为static_cast的缓冲区

[英]using *void as a buffer for static_cast

So I go this: 所以我去这个:

class A;

class B : public A;

class C : public B;

vector<A*> *vecA;

vector<C*> *vecC;

And I want to cast a vectC into a vecA. 我想将vectC转换为vecA。

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

So I used void pointer as a buffer and the cast: 因此,我将void指针用作缓冲区和演员表:

void *buffer = vecC;

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

Is this valid? 这有效吗? Is there another way to do it? 还有另一种方法吗?

You should just have a std::vector<A*> and then when you wish to put a B or C inside, you can do this: 您应该只具有一个std::vector<A*> ,然后当您希望在其中放入BC ,可以这样做:

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

This will work much better than anything you're currently doing. 这将比您目前正在执行的任何操作都要好得多。

Also, you should use std::unique_ptr or std::shared_ptr , depending on ownership semantics of your pointers. 另外,根据指针的所有权语义,应使用std::unique_ptrstd::shared_ptr Owning raw pointers are a no-no!! 拥有原始指针是不行的!!

Is this valid? 这有效吗?

No it's not. 不,这不对。 It is completely undefined what happens if you access it. 完全不确定,如果您访问它会发生什么。

Is there another way to do it? 还有另一种方法吗?

Yes. 是。 It depends on what you want to do: 这取决于您想做什么:

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

  2. create an adaptor which behaves as random access container of A* if given a container or iterator of C* or any other derived type 如果给定C*的容器或迭代器或任何其他派生类型,则创建一个充当A*随机访问容器的适配器

  3. I am sure there are other solutions, just tell us what you want to do 我确定还有其他解决方案,只需告诉我们您想做什么

It looks to me as if you're looking for covariant support for generic (template) types. 在我看来,您似乎正在寻找对通用(模板)类型的协变支持。 This is not supported at all by C++. C ++完全不支持此功能。 It is supported by the CLR - and C#/VB - though only in the latest versions. CLR和C#/ VB支持它,尽管仅在最新版本中支持。

In spite of this, to echo others' responses, you're likely barking up the wrong tree. 尽管如此,要呼应他人的回应,您可能会吠叫错误的树。 My hunch is that you want to have a vector of pointers to A-typed objects... and this type should include virtual methods and a virtual destructor - as necessary. 我的直觉是,您希望有一个指向A型对象的指针的向量……并且这种类型应包括虚方法和虚析构函数-必要时。 It's impossible to be more specific about a suitable alternative approach without a better understanding of the high-level problem you're trying to solve - which is not evident from your question. 如果没有更好地了解您要解决的高级问题,就不可能更具体地讨论合适的替代方法,这在您的问题中并不明显。

The magic words you probably needed to know are "covariance" and "contravariance". 您可能需要知道的魔术词是“协方差”和“逆方差”。 Have a look here for a very closely related issue. 在这里查看一个非常相关的问题。

Short answer: there's no neat, sensible way to do the conversion you want to do merely with casts. 简短的答案:没有一种整洁,明智的方法可以仅通过强制转换来进行您想要的转换。 You will need to copy to contents of your old vector the long way into your new vector. 您将需要很长一段时间才能将新载体复制到旧载体的内容中。

But more importantly: 1. Don't ever use new on a standard container type. 但更重要的是:1.永远不要在标准容器类型上使用new 2. Don't pass around pointers to standard container types. 2.不要传递指向标准容器类型的指针。 3. Don't pass around raw pointers to your own objects, use std::shared_ptr instead. 3.不要将原始指针传递给自己的对象,而应使用std::shared_ptr

Instead of detouring via void* , with C++11 just use reinterpret_cast . 在C ++ 11中,不要通过void*绕行,而只需使用reinterpret_cast

However, the conversion that you desire permits very ungood things : 但是,您想要的转换允许非常不好的事情

#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
}

It's roughly the same issue that you have with converting T** to T const** (not permitted, could allow ungood things). 与将T**转换为T const**大致相同(不允许,可能会带来不好的事情)。 The short of it is, don't do this unless you know exactly what you're doing. 简而言之,除非您确切知道自己在做什么,否则不要这样做。 The longer of it, hm, well, there's not room to discuss it here, but it involves differentiating between mutable and immutable collections, and being very very careful. 它的时间较长,嗯,这里没有讨论的余地,但是它涉及区分可变和不可变的集合,并且要非常小心。


edit: as others (who did not address the conversion question) have already stated, a practical solution is a vector of A pointers, or smart pointers, and then using C++ polymorphism (ie virtual member functions). 编辑:正如其他人(未解决转换问题)已经指出的那样,一个实际的解决方案是A指针或智能指针的向量,然后使用C ++多态性(即虚拟成员函数)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM