------------ ------------
| TclObjct | | Handler |
------------ ------------
|__________________________________|
|
--------------
| NsObject |---> virtual void recv(Packet*,Handler* callback = 0) = 0;
--------------
|
--------------
| Connector |
--------------
|
________________________________
| |
| -------------
| | Agent |
| -------------
| |
| -------------
| | OLSR |
------------- -------------
| Queue |-----> virtual void recv(Packet*, Handler*);
-------------
|
-------------
| DropTail |
-------------
|
-------------
| PriQueue |-----> void recv(Packet* p, Handler* h);
--------------亲爱的,我正在使用NS2实现一个网络编码协议。但是几天来,我一直被困在一个问题上,那就是如何在类之间交叉引用以及传递“这个”指针的方法。
类层次结构如上图所示(请原谅,我是这个站点的新用户,不允许发布图片)。
在程序中,我必须创建一个从" PriQueue“类到" OLSR”类的连接,我认为交叉引用可能是一种很好的方法(从OLSR到PriQueue的连接是使用指针‘NS2 _’自动设置的,它的类型是NsObject*)。
代码的一部分如下所示。但问题是,指针"olsr_callback“始终为空。因此,当从add_rr_ack对象调用函数PriQueue ()时,访问'ra_addr_‘变量的行将生成分段错误。
(如果"nsaddr_t addr = ra_addr();“行被阻塞,程序工作正常)
交叉引用机制从本页获得:第4条所述的交叉参照。
我想这就是我试图在send_pkt()中传递"this“指针的方法的问题。但我不知道是怎么回事。如果你有什么想法,请帮帮我。
任何帮助都将不胜感激。
舒。
//------OLSR.h--------//
class PriQueue;
class OLSR : public Agent {
......
nsaddr_t ra_addr_;
void send_pkt();
......
public:
inline nsaddr_t& ra_addr() { return ra_addr_; }
Packet* add_rr_ack(Packet*,PriQueue*);
......
}
//------OLSR.cc------//
#include<olsr/OLSR.h>
#include<queue/priqueue.h>
void OLSR::send_pkt() {
......
......
target_->recv(p,this); // 'target_' points to the respective priqueue object
// during the runtime
}
Packet* OLSR::add_rr_ack(Packet* p, PriQueue*) {
......
nsaddr_t addr = ra_addr(); // Generate a segmentation error!!!!!
.......
return p;
}
......
//------priqueue.h------//
class OLSR;
class PriQueue : public DropTail {
public:
void recv(Packet* p, Handler* h);
......
Packet* deque();
OLSR* olsr_callback;
......
}
//------priqueue.cc------//
#include<olsr/OLSR.h>
#include "priqueue.h"
PriQueue::PriQueue() : DropTail(),olsr_callback(NULL) {......}
PriQueue::recv(Packet* p, Handler* h) {
......
olsr_callback = dynamic_cast<OLSR*>(h);
//Debug
printf("Packet received through recv() in PriQueue. \n");
......
}
PriQueue::deque() {
.....
Packet* p = q_->deque();
if(olsr_callback == NULL) printf("CALLBACK is NULL. \n");
Packet* p1 = olsr_callback->add_rr_ack(p);
.....
}P.S:我还尝试将PriQueue类中的recv()函数更改如下:
//------priqueue.h------//
void recv(Packet* p, OLSR* h);
// ------priqueue.cc-----//
void PriQueue::recv(Packet* p, OLSR*h) {
......
olsr_callback = h;
......
}但是,在本例中,当我们从send_pkt()调用recv()函数时。它实际上将调用基类队列的recv()函数,而不是按预期调用PriQueue的recv()函数。
发布于 2010-09-29 09:32:31
class OLSR : public Agent您的OLSR类来自某个类'Agent‘(我不知道它是什么)。我假设这不是从'Handle‘派生出来的类之一(因为它没有显示在图表中)。
因为'OLSR‘不是从’句柄‘派生出来的,所以’句柄‘到'OLSR’的dynamic_cast失败。您可以从多态库到派生类执行dynamic_cast,而不是对无关的类执行。
发布于 2010-09-29 17:19:01
下面的代码适用于我的编译器。它输出"20",这是我给成员OLSR::ra_addr_的值。我不得不添加一些未声明的假设,以便进行编译:
recv(),因此它不是抽象的。Handler*与dynamic_cast一起使用将是错误的,您的编译器应该会抱怨)。Packet::get()。这只是给我一个指针,这样我就可以调用匹配您签名的函数了。如果您无法理解为什么您的代码不能工作,请始终尝试以下操作:复制您所有的代码,然后每次删除一些东西,直到您找出问题所在,或者得到一个简单的示例,您可以完整地发布,并问它为什么不能实现您的期望。
#include <iostream>
class Packet {
public:
static Packet* get() { return &dummy_; }
private:
static Packet dummy_;
};
Packet Packet::dummy_;
class Handler {
public:
virtual ~Handler() {}
};
class NsObject : public Handler {
public:
virtual void recv(Packet*, Handler* callback = 0) = 0;
};
class Connector : public NsObject {};
class Queue : public Connector {
public:
virtual void recv(Packet*, Handler*) {}
};
class DropTail : public Queue {};
class OLSR;
class PriQueue : public DropTail {
public:
inline PriQueue() : DropTail(), olsr_callback(NULL) {}
void recv(Packet* p, Handler* h);
Packet* deque();
private:
OLSR* olsr_callback;
};
class Agent : public Connector {};
class OLSR : public Agent {
public:
explicit OLSR(int ra_addr) : Agent(), ra_addr_(ra_addr) {}
inline int ra_addr() { return ra_addr_; }
void send_pkt(PriQueue* q);
Packet* add_rr_ack(Packet* p, PriQueue*);
virtual void recv(Packet*, Handler*) {}
private:
int ra_addr_;
};
void PriQueue::recv(Packet* p, Handler* h) {
olsr_callback = dynamic_cast<OLSR*>(h);
}
Packet* PriQueue::deque() {
return olsr_callback->add_rr_ack(Packet::get(), this);
}
void OLSR::send_pkt(PriQueue* q) {
q->recv( Packet::get(), this );
}
Packet* OLSR::add_rr_ack(Packet* p, PriQueue*) {
std::cout << ra_addr() << std::endl;
return p;
}
int main() {
PriQueue q;
OLSR olsr(20);
olsr.send_pkt(&q);
q.deque();
return 0;
}发布于 2010-09-30 07:29:59
谢谢你们的帮助,Chubsdad和aschepler。我找到了问题所在。
通常,使用以下语句将数据包调度为模拟时间线上的事件:
Scheduler::instance().schedule(target_,p,0.0);其中p是抛给事件的数据包;'0.0‘是事件的延迟时间,在本例中是零;关键参数'target_’是处理事件的处理程序。
下面是类NsObject的一部分及其实现:
//----------- object.h ----------//
class NsObject : public TclObject, public Handler {
public:
NsObject();
virtual ~NsObject();
virtual void recv(Packet*, Handler* callback = 0) = 0;
protected:
void handle(Event*);
}
//------------ object.cc -----------//
void NsObject::handle(Event* e)
{
recv((Packet*)e); // In my case, this will call the recv(Packet*,Handler*) of PriQueue class.
}下面是类Handler的实现:
class Handler {
public:
virtual ~Handler() {}
virtual void Handler(Event* event) = 0;
}根据我以前对NS2的理解,我尝试使用
target_->recv(p,h); 为了避免事件调度,直接调用recv(Packet*, Handler*)函数的PriQueue,结果证明是错误的。
尽管使用了NsObject::handle(),但控件仍将进入target_->recv(p,h),因为NsObject::handle()函数只接受Event*类型参数,Handler*参数将始终丢失。这就是为什么olsr_callback变量总是为空的。(在调试过程中已经验证了这一点。)
因此,下一步是对NsObject做一些调整,即使我仍然不完全理解在使用target_->recv(p,h)时它是如何进入函数NsObject::recv()的。:)
再次感谢你的帮助。
舒舒
https://stackoverflow.com/questions/3820214
复制相似问题