多态队列
我正在尝试实现一个多态队列。 这是我的试验:
QQueue <Request *> requests;
while(...)
{
QString line = QString::fromUtf8(client->readLine()).trimmed();
if(...)){
Request *request=new Request();
request->tcpMessage=line.toUtf8();
request->decodeFromTcpMessage(); //this initialize variables in request using tcpMessage
if(request->requestType==REQUEST_LOGIN){
LoginRequest loginRequest;
request=&loginRequest;
request->tcpMessage=line.toUtf8();
request->decodeFromTcpMessage();
requests.enqueue(request);
}
//Here pointers in "requests" do not point to objects I created above, and I noticed that their destructors are also called.
LoginRequest *loginRequest2=dynamic_cast<LoginRequest *>(requests.dequeue());
loginRequest2->decodeFromTcpMessage();
}
}
不幸的是,由于我在第二条评论中提到的原因,我无法使用此代码来使多态队列工作。我想,我需要使用智能指针,但是如何呢? 我愿意接受我的代码的任何改进或多态队列的新实现。
谢谢。
I'm trying to implement a Polymorphic Queue.
Here is my trial:
QQueue <Request *> requests;
while(...)
{
QString line = QString::fromUtf8(client->readLine()).trimmed();
if(...)){
Request *request=new Request();
request->tcpMessage=line.toUtf8();
request->decodeFromTcpMessage(); //this initialize variables in request using tcpMessage
if(request->requestType==REQUEST_LOGIN){
LoginRequest loginRequest;
request=&loginRequest;
request->tcpMessage=line.toUtf8();
request->decodeFromTcpMessage();
requests.enqueue(request);
}
//Here pointers in "requests" do not point to objects I created above, and I noticed that their destructors are also called.
LoginRequest *loginRequest2=dynamic_cast<LoginRequest *>(requests.dequeue());
loginRequest2->decodeFromTcpMessage();
}
}
Unfortunately, I could not manage to make work Polymorphic Queue with this code because of the reason I mentioned in second comment.I guess, I need to use smart-pointers, but how?
I'm open to any improvement of my code or a new implementation of polymorphic queue.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的源代码中有两个问题:
Request *request=new Request();
声明内存,该内存被后面的request=&loginRequest;
分配放弃(并且不再可删除)LoginRequest loginRequest;
变量会被破坏,从而导致中出现悬空指针
request
我建议删除
Request *request=new Request();
行,然后在if(...){
块中分配具体的LoginRequest
对象由您可以通过在队列中的对象弹出时(处理后)手动删除它们来删除它们,或者使用容器安全的智能指针< /strong> 在队列中(boost::shared_ptr 没问题,也许 QT 也有其中之一,std::auto_ptr 不是容器安全的)。
PITFALL 另外请确保 Request 的析构函数是虚拟的,因为当基类中没有虚拟析构函数时,您无法通过指向其基类的指针删除对象(c++ 可以使用以下命令调用基类析构函数)在这种情况下,派生类实例会导致未定义的行为,例如内存泄漏或崩溃)
There are 2 problems in your source:
Request *request=new Request();
, which gets abandoned by the laterrequest=&loginRequest;
assignment (and is no longer deletable)LoginRequest loginRequest;
variable gets destructed when the execution leaves the {} block where the variable is defined, resulting in a dangling pointer inrequest
I would suggest to remove the
Request *request=new Request();
line, and later in theif(...){
block assign the concreteLoginRequest
object byYou can get rid of the queued objects by deleting them manually when they got poped out of the queue (after they are processed), or by using a container-safe smartpointer in the queue (boost::shared_ptr is fine, maybe QT has also one of them, std::auto_ptr IS NOT container-safe).
PITFALL Also make sure that the destructor of Request is virtual, since you cannot delete objects by a pointer to its base classe when there is no virtual destructor in the base class(c++ can call the base class destructor with the derived class instance in this case, leading in undefined behavior like memory leaks or crashes)
您将无效的指针放入
QQueue
。如果您的QQueue
保存指针,您需要在堆上创建插入其中的每个对象,即通过调用new
。另外,如果不需要,请不要忘记释放第一个创建的Request
。我认为您应该将代码重写为:
使用此代码,您以后的
dynamic_cast
将不会失败。You are putting invalid pointer to your
QQueue
. If yourQQueue
holds pointers, you need to create every object you insert to it on the heap, i.e. with a call tonew
. Also, do not forget to free the first createdRequest
if you do not need it.I think you should rewrite your code to:
With this code, your later
dynamic_cast<LoginRequest*>
will not fail.从代码片段中我可以立即看到 Request 对象已排队,稍后您尝试将其向下转换为 LoginRequest。 dynamic_cast 理所当然会失败。您必须解析请求数据并创建从 Request 派生的适当类的对象。我建议为此使用工厂模式。
Immediately from the code snippet I can see that an object of Request is queued and later you try to downcast it to LoginRequest. dynamic_cast will rightfully fail. You have to parse request data and create objects of appropriate class, derived from Request. I would suggest using Factory Pattern for this.
在我看来,这也是一个使用工厂的好地方。
其中
...然后,自然地,您的构造函数会对该消息执行正确的操作,正确初始化对象。
This is also a good place to use factories, IMO.
where
...and then, naturally, your constructors do the right thing with the message, initializing the objects properly.