首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >交叉引用并在类之间传递此指针[NS2/C++]

交叉引用并在类之间传递此指针[NS2/C++]
EN

Stack Overflow用户
提问于 2010-09-29 09:13:36
回答 3查看 1.7K关注 0票数 4
代码语言:javascript
复制
              ------------                       ------------
              | 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“指针的方法的问题。但我不知道是怎么回事。如果你有什么想法,请帮帮我。

任何帮助都将不胜感激。

舒。

代码语言:javascript
复制
//------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()函数更改如下:

代码语言:javascript
复制
//------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()函数。

EN

回答 3

Stack Overflow用户

发布于 2010-09-29 09:32:31

代码语言:javascript
复制
class OLSR : public Agent

您的OLSR类来自某个类'Agent‘(我不知道它是什么)。我假设这不是从'Handle‘派生出来的类之一(因为它没有显示在图表中)。

因为'OLSR‘不是从’句柄‘派生出来的,所以’句柄‘到'OLSR’的dynamic_cast失败。您可以从多态库到派生类执行dynamic_cast,而不是对无关的类执行。

票数 1
EN

Stack Overflow用户

发布于 2010-09-29 17:19:01

下面的代码适用于我的编译器。它输出"20",这是我给成员OLSR::ra_addr_的值。我不得不添加一些未声明的假设,以便进行编译:

  • OLSR或某些父级定义了recv(),因此它不是抽象的。
  • 类Handler至少有一个虚拟函数(否则,将Handler*与dynamic_cast一起使用将是错误的,您的编译器应该会抱怨)。
  • 你会在某个时候给OLSR::send_pkt打电话。我想您已经检查了它的调试输出行。(但也许它是用不同的PriQueue对象调用的?)
  • 忽略Packet::get()。这只是给我一个指针,这样我就可以调用匹配您签名的函数了。

如果您无法理解为什么您的代码不能工作,请始终尝试以下操作:复制您所有的代码,然后每次删除一些东西,直到您找出问题所在,或者得到一个简单的示例,您可以完整地发布,并问它为什么不能实现您的期望。

代码语言:javascript
复制
#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;
}
票数 1
EN

Stack Overflow用户

发布于 2010-09-30 07:29:59

谢谢你们的帮助,Chubsdad和aschepler。我找到了问题所在。

通常,使用以下语句将数据包调度为模拟时间线上的事件:

代码语言:javascript
复制
Scheduler::instance().schedule(target_,p,0.0);

其中p是抛给事件的数据包;'0.0‘是事件的延迟时间,在本例中是零;关键参数'target_’是处理事件的处理程序。

下面是类NsObject的一部分及其实现:

代码语言:javascript
复制
   //----------- 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的实现:

代码语言:javascript
复制
   class Handler {
   public:
       virtual ~Handler() {}
       virtual void Handler(Event* event) = 0;
   }

根据我以前对NS2的理解,我尝试使用

代码语言:javascript
复制
   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()的。:)

再次感谢你的帮助。

舒舒

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3820214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档