为什么这个static_cast不被允许?

12

我有一个A类对象,我想将其分配在自定义堆栈对象上。为了做到这一点,我只需将堆栈指针移动与对象大小相同的字节数并返回其先前的值:

class A : public B {}; //B is from a precompiled library

class stack {
public:
    stack(void): _top(&_storage[0]) {}

    template <typename T>
    inline T* push(void) {
        T* ptr = static_cast<T*>(_top);

        _top += sizeof(T);

        return ptr;
    }

    //...

private:
    char _storage[1024];
    char* _top;
};

stack _stack;

int main(int argc, char** argv) {
    A* a = _stack.push<A>(); //ignore the lack of a constructor call

    return 0;
}

Visual C++提示我,static_cast无法将char*转换为A*。普通的C样式转换不会出现这个错误,但我更愿意更明确地避免使用动态转换(A继承自另一个类,但不参与vtable,因此没有)。在这种情况下,两者有什么区别吗?

3个回答

19

按设计。

static_cast 转换没有被设计用于转换不相关的指针类型,你需要使用 reinterpret_cast。如果你想明确指定你正在进行的转换,则使用正确的那个。在这种情况下,C 风格转换将执行一个 reinterpret_cast

你真的需要研究一下不同的转换运算符,因为关于 dynamic_cast 的注释也没有太多意义。


我原本认为 dynamic_cast 可以改变对象的动态类型,这不正确吗? - NmdMystery
1
@NmdMystery:没有什么能改变对象的 动态类型。一个对象在构造时就已经有了类型,而类型永远不会改变(引用或指针可能具有不同的类型,例如基类,但对象始终是相同类型的)。再次强调,最好的方法是查阅书籍或教程,澄清你的疑问。 - David Rodríguez - dribeas
1
好吧,这是一个诚实的错误,我以为我已经对每个转换有了相当好的理解。看来不是这样。 - NmdMystery
@NmdMystery:别担心。如果被认为不是诚实的错误,可能会有几个投票关闭。 - David Rodríguez - dribeas

7

正如其他人所说,解决方案是使用reinterpret_cast,它的作用是用于在不相关的指针类型之间进行转换:

T* ptr = reinterpret_cast<T*>(_top);

如果您使用placement new,不仅可以避免转换问题,还可以解决对于具有构造函数的类型未调用构造函数的问题:
T* ptr = new(_top) T();

3

从char*到A*没有隐式或显式的转换。您需要使用reinterpret_cast<>来执行此类型的转换。

有关详细信息,请参见此SO答案


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接