Question

I am having some trouble really understanding the limits of using references instead of pointers: How can I pass a derived object with no virtual functions, just a tuple of data, into a list of based objects?

In my application, there is an event object and a queue:

class Event {
    String name;
public:
    Event(const String &name_);
};

class KeyEvent : public Event {
public:    
    int key;
};

std::queue<Event> eventsQueue;

When I cast objects from the queue to their original types, I get undefined values in all the variables, which never happened with pointers. So basically,

while(!eventsQueue.empty()) {
    auto &e = eventsQueue.front();
    if(e.name == "keyPress") {
        std::cout << static_cast<KeyEvent &>(e).key;
    }  
}

gives me gibberish: http://ideone.com/rbzGJV

Is there a way to fix this without using the pointers? Is there a way to have a reference inside a container like std::queue?

Was it helpful?

Solution

An Event is a block of memory with a particular size, which is the size of a String object. A KeyEvent is a block of memory with a size of sizeof(Event) + sizeof(int) which is 4 bytes (probably) bigger. You are storing things in a container of Event types, so each element in the container has a size of Event, and the int will ... well ... it will fall off the end into undefined behaviour territory. By storing pointers instead each element in the container will be the size of the pointer type, no matter what it is pointing to.

I have no idea what you did in order to ram those KeyEvent objects into an Event container, but whatever it was I recommend not doing it anymore!

P.S. Your phrasing suggests a Java background? In C++ "Event e;" is not a reference, it is an Event. Event & e; is a reference to an event. Event * e; is a pointer to an event; Event & e is implemented internally as a pointer in most C++ compilers but you shouldn't have to care. I e; think the closest thing in behaviour to what Java would do if you said Event e; is std::shared_ptr<Event>

OTHER TIPS

Your queue contains Event objects, so when you push a KeyEvent, it is an implicit cast to Event and then an Event object is copy-constructed in the queue. Then you cast what is an Event object to a KeyEvent, which means you start reading the memory for the key field from outside the object, hence the garbage.

If you want to have polymorphic types, you should use pointers.

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