Question

I have a question about c++ cast operators.

Suppose you have a class Message and several subclasses: Message1 Message 2 etc.

Suppose you have a class Event and also different subclasses of Event: Event 1 Event 2

In both cases I can distinguish the type of the subclass from an ID (such as field)

class Message {
....
int MessageID;
}

class Message1 : public Message {
//other fields;
}

class Message2 : public Message {
//other fields;
}

class Event {
int eventID;
}

class Event1 {
Message theMessage;

Message getMessage();
}

class Event2 {
Message theMessage;
}

I insert instances Event1 or Event2 into a vector<Event> in this case, when I extract an Event by the carrier, though I'm sure you have an instance of Event1, it is correct to use the static_cast? For example:

    Event theEvent = myVector.at(i);
    Event1 *e1 = static_cast<Event1*>(&theEvent);
    if(e1->getID() == xxx) {
    Message2 *m2 = static_cast<Message2*>(&e1->getMessage());
    }

I have a problem: after the last cast, I do not see instance information as Message2 (always only those of its parent class Message) In this case, is necessary to use dynamic_cast?

Was it helpful?

Solution

e1->getMessage() returns an object of type Message, not a pointer. So your data will be sliced. Additionally you cast a pointer to a temporary here:

Message2 *m2 = static_cast<Message2*>(&e1->getMessage());

You can do this if you return a pointer.

Message * getMessage() { return &theMessage; }

static_cast is the correct way of casting base pointers to derived pointers without any runtime checks. The "safer" way of doing this is to use dynamic_cast operator of course, since it will perform a runtime-check upon casting a derived to a base pointer or reference. (I guess I'm going to be stoned to death here if I tell you to stick to static_cast to avoid those checks if you got your own that is fail-proof. ;))

The best way (in my opinion) would be a proper virtual interface design in the base classes. You could avoid casting from base to derived this way.

Additionally you slice all your Events if you use a vector<Event>. You can only use vector<Event*> to have your collection of derived objects since a Base pointer may point to derived objects but Base objects cannot hold Derived Data. (All derived Events in your vector will miss theMessage and only have the data contained in Event.)

OTHER TIPS

Typically, when you have derived classes, you should be using virtual functions.

In your example, perhaps the "content" in the message could be got through a virtual function.

This cast:

    Event1 *e1 = static_cast<Event1*>(&theEvent);

will not work. theEvent is smaller than Event1 by a Message - which means that whatever message you get out of it will be "random garbage", because you only had an Event in the first place.

If you want to store "any type of event" in your events array, then you need to store pointers to the Event type, or you will definitely suffer from the slicing problem you have above.

Your idea, as presented is completely hopeless. You store all base classes by value in structures and the vector. That means they will be exactly that base class type, never any of your derived ones. Thus casting will not help you a bit.

You have to read up on how to store polymorphic objects in collections or structures. (basicly through some kind of pointers, arrangling ownership issues correctly).

After you resolved the storage issue, you can come back for the casting one -- that will be easy in comparison.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top