0

我在真正理解使用引用而不是指针的限制时遇到了一些麻烦:如何将没有虚函数的派生对象(只有一个数据元组)传递到基于对象的列表中?

在我的应用程序中,有一个事件对象和一个队列:

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

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

std::queue<Event> eventsQueue;

当我将队列中的对象转换为它们的原始类型时,我在所有变量中都得到了未定义的值,而指针从未发生过这种情况。所以基本上,

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

给我胡言乱语:http: //ideone.com/rbzGJV

有没有办法在不使用指针的情况下解决这个问题?有没有办法在容器内有引用std::queue

4

2 回答 2

1

事件是具有特定大小的内存块,即字符串对象的大小。KeyEvent 是一个大小为 sizeof(Event) + sizeof(int) 的内存块,比它大 4 个字节(可能)。您将事物存储在 Event 类型的容器中,因此容器中的每个元素都有一个 Event 大小,并且 int 将......好吧......它最终会落入未定义的行为领域。通过存储指针,容器中的每个元素都将是指针类型的大小,无论它指向什么。

我不知道您为了将这些 KeyEvent 对象撞到 Event 容器中做了什么,但无论它是什么,我建议不要再这样做了!

PS您的措辞暗示Java背景?在 C++ 中的“事件 e;” 不是参考,它是一个事件。事件 & e; 是对事件的引用。事件 * e; 是指向事件的指针;Event & e 在大多数 C++ 编译器中作为指针在内部实现,但您不必关心。IE; 如果你说的话,认为与 Java 最接近的行为Event e;std::shared_ptr<Event>

于 2014-01-26T00:34:11.960 回答
0

您的队列包含 Event 对象,因此当您推送 KeyEvent 时,它是对 Event 的隐式强制转换,然后在队列中复制构造 Event 对象。然后您将 Event 对象转换为 KeyEvent,这意味着您开始从对象外部读取键字段的内存,因此是垃圾。

如果你想拥有多态类型,你应该使用指针。

于 2014-01-26T00:43:25.957 回答