12

I have an object of class A that I want to allocate on a custom stack object. To do this, I simply move the stack pointer as many bytes as the object is in size and return its previous value:

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++ simply tells me that static_cast cannot convert from char* to A*. A regular C style cast does not give me this error, but I'd rather be more explicit and avoid a dynamic cast (A inherits from another class, but does not contribute to the vtable it doesn't have). Is there any difference between the two in this case?

NmdMystery
  • 2,778
  • 3
  • 32
  • 60

3 Answers3

19

By design.

The static_cast conversion is not designed to convert between unrelated pointer types, for that you need to use reinterpret_cast. If you want to be explicit about the cast you are doing, then use the correct one. The C style cast will do a reinterpret_cast in this case.

You really need to research about the different cast operators, as the comment on dynamic_cast does not make much sense either.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • I thought I understood that dynamic_cast changes the dynamic type of an object, is that not correct? – NmdMystery Jan 15 '14 at 05:44
  • 1
    @NmdMystery: Nothing changes the *dynamic type* of an object. An object is of a type when it is constructed and the type never changes (references or pointers may have a different type, as in a base, but the object is always of the same type). Again, the best you can do is to reach for a book or tutorial and clear up your doubts. – David Rodríguez - dribeas Jan 15 '14 at 05:48
  • 1
    Well it was an honest mistake, I thought I already had a pretty good idea of what each cast did. Guess not. – NmdMystery Jan 15 '14 at 05:53
  • @NmdMystery: No worries. If it had been deemed anything other than a honest mistake there probably would be a few votes to close. – David Rodríguez - dribeas Jan 15 '14 at 21:54
7

As others have said, the solution is to use reinterpret_cast, which is meant to be used when casting between unrelated pointer types:

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

If you use placement new instead, you not only avoid the casting problem but you also fix the problem of not calling the constructor for types that have a constructor:

T* ptr = new(_top) T();
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
3

There is no implicit or explicit conversion from char* to A*. You want reinterpret_cast<> to perform this type of cast.

For more detail, see This SO answer

Community
  • 1
  • 1
sbaker
  • 437
  • 2
  • 7