views:

109

answers:

1

Hi,

I have a forward deceleration problem. I had a normal class before, called GlobalCWND, it was instantiated and used in another class ProtocolContext.

I forward declare the ProtocolContext class in Requestor.h.

You can see the related part of the code of this 2 classes.

============Protocol Context========

 class Requestor<RequestorStrategy>;
 class Receiver<ReceiverStrategy>;

 class ProtocolContext : public Object
 {
 public:
   ProtocolContext(Ptr<SubscriptionContext> , Ptr<ReceiverStrategy> , Ptr<
       RequestorStrategy> );
.......

 ProtocolContext::ProtocolContext(Ptr<SubscriptionContext> sctx, Ptr<
      ReceiverStrategy> rec, Ptr<RequestorStrategy> req) :
    receiver(rec), requestor(req)
  {
    m_sctx = sctx;
    Ptr<GlobalCWND> m_globalCWND = Create<GlobalCWND> (this);
    cout << "Initializing Protocol Context for rid"
        << m_sctx->GetMetaDataStrategy()->GetRid() << endl;
    m_ph = Create<PacketHandler> (sctx);
  }

=================Requestor.h=========

 class ProtocolContext;

 class RequestorStrategy : public Object
 {

 public:
   RequestorStrategy()
   {
   }
   ;
   ~RequestorStrategy()
   {
   }
   ;
   /* Transitions */
   virtual void
   Trans(Ptr<ProtocolContext> , Ptr<Packet> ) = 0;
 };

.....

It worked properly before. Now I have change the GlobalCWND to a virtual class and In the protocol Context constructor I have this code:

ProtocolContext::ProtocolContext(Ptr<SubscriptionContext> sctx, Ptr<
      ReceiverStrategy> rec, Ptr<RequestorStrategy> req) :
    receiver(rec), requestor(req)
  {
    m_sctx = sctx;
    Ptr<GlobalCWND> m_globalCWND = Create<GlobalCWNDSimple> (this);

..............
}

But now I get this error:

 GlobalCWND.h:21:   instantiated from here
ptr.h:441: error: invalid use of incomplete type ‘struct
ProtocolContext’
Requestor.h:16: error: forward declaration
of ‘struct ProtocolContext’

the error lines are:

line 21 of GlobalCWND() is    GlobalCWND (){};
and line 16 of Requestor.h is class ProtocolContext;

Ptr class is actually creating pointer to the object, line 441 of ptr.h is the last line of this function:

template <typename T>
Ptr<T>::~Ptr ()
{
 if (m_ptr != 0)
   {
     m_ptr->Unref();
   }
}

The code for GlobalCWND starts like this:

 class ProtocolContext;

  class GlobalCWND : public Object
  {
  public:
    GlobalCWND (){};
    GlobalCWND (Ptr<ProtocolContext>){};
    ~GlobalCWND (){};

    static TypeId GetTypeId(){
      static TypeId tid = TypeId("GlobalCWND")
      .SetParent<Object> ()
      ;
      return tid;
    };
+2  A: 

The constructor for GlobalCWND takes a Ptr<ProtocolContext> by value, which in its destructor calls a method on the ProtocolContext pointer.
According to the error however, ProtocolContext is incomplete at that point - you need to include the declaration for ProtocolContext.
For a list on what you can and can't do with incomplete types, see this answer.

Georg Fritzsche
I have the ´class ProtocolContext;´ included in the ´GlobalCWND´ that does not count for anything?
somaya
@som: That is a forward declaration and forward declarations only give you incomplete types. You only can do a limited amount of things with incomplete types and calling methods is not one of them - see e.g. [this answer](http://stackoverflow.com/questions/553682/when-to-use-forward-declaration/553869#553869).
Georg Fritzsche
Thanks Georg. Just trying to understand better I don't get the fact that the code works correctly when the GlobalCWND is using normal functions and not virtual ones. What causes the error to only happen in the case, where I have pure virtual functions defined.( I am pretty sure in all the places in the header files I am using Ptr<ProtocolContext> which basically equals using *ProtocolContext )
somaya
@som: Wether you are using virtual methods in this case shouldn't make any difference. Maybe you introduced another change at the same time as making the methods virtual?
Georg Fritzsche
I don't think, there is any other change. I have done quite simple changes. First made the base class `GlobalCWND.h` virtual and removed the `GlobalCWND.cc`. I have then created another class `GlobalCWNDSimple` inherited from the `GlobalCWND`. The new class contains full function definitions. Then as can be seen in my code sample, I have changed one line in the `ProtocolContext`. My change was instead of instantiating a pointer to `GlobalCWND` I have instantiated a pointer to `GlobalCWNDSimple`, assigning this to the local `GlobalCWND` pointer defined there.
somaya
@som: Maybe you had the neccessary include for `ProtocolContext` in `GlobalCWND.cc`? Whatever the reason, you need the declaration for `ProtocolContext` to be visible if you want to call methods on it.
Georg Fritzsche