circular dependency...

Discussion in 'C++' started by Rob Clark, Nov 28, 2005.

  1. Rob Clark

    Rob Clark Guest

    Hi,

    I have an issue which is the ordinary and always recurring circular
    dependency - but I do not know how to resolve it :-( The usual forward
    declaration does not help...

    I have a client that uses a resource. As a consequence of using the
    resource, the resource later receives an asynchronous notification (from an
    underlying layer, e.g. OS). This notification should then be forwarded to
    the Client that owns the resource.

    In code this looks something:

    int main()
    {
    Resource resource; // Define the resource
    Client client(&resource); // Configure the client to own the resource
    client.Execute(); // Execute operation, which in turn uses the
    resource

    RunEventLoopForever();
    }


    class Resource
    {
    Client* m_client;
    public:
    void SetClient(Client* client)
    {
    m_client = client;
    }

    void Use()
    {
    // Use this resource
    // DoSomethingInteresting()
    }
    void AsyncNotification()
    {
    m_client->Notify();
    }
    };

    class Client
    {
    Resource* m_resource;
    public:
    Client(Resource* res) : m_resource(res)
    {
    m_resource->SetClient(this);
    }
    void Execute()
    {
    m_resource->Use();
    }
    void Notify()
    {
    // Handle notification
    // m_resource->Whatever()
    }
    };

    What should I do to resolve this issue?
    Complete redesign? Rather not - I like this simple design (besides it
    doesn't work...)
    Introducing something in between to break the dependency? If so - what?

    Thanks in advamce!
    /Rob
     
    Rob Clark, Nov 28, 2005
    #1
    1. Advertisements

  2. Rob Clark wrote:

    > class Resource
    > {
    > Client* m_client;
    > public:
    > void SetClient(Client* client)
    > {
    > m_client = client;
    > }
    >
    > void Use()
    > {
    > // Use this resource
    > // DoSomethingInteresting()
    > }
    > void AsyncNotification()
    > {
    > m_client->Notify();
    > }
    > };
    >
    > class Client
    > {
    > Resource* m_resource;
    > public:
    > Client(Resource* res) : m_resource(res)
    > {
    > m_resource->SetClient(this);
    > }
    > void Execute()
    > {
    > m_resource->Use();
    > }
    > void Notify()
    > {
    > // Handle notification
    > // m_resource->Whatever()
    > }
    > };
    >
    > What should I do to resolve this issue?


    Donot define member functions inside the class. Simply declare them.
    Define them outside the class. Use inline if you want them to be
    inlined. Then simply declare the required class.

    //header file Resource.h
    class Client;
    class Resource
    {
    Client* m_client;
    public:
    void SetClient(Client* client);
    void Use();
    void AsyncNotification();
    };

    // definitions will go in Resource.cpp. Include Resource.h there.

    HTH.
     
    Neelesh Bodas, Nov 28, 2005
    #2
    1. Advertisements

  3. Rob Clark

    John Carson Guest

    "Rob Clark" <> wrote in message
    news:v%Bif.49$
    > Hi,
    >
    > I have an issue which is the ordinary and always recurring circular
    > dependency - but I do not know how to resolve it :-( The usual
    > forward declaration does not help...
    >
    > I have a client that uses a resource. As a consequence of using the
    > resource, the resource later receives an asynchronous notification
    > (from an underlying layer, e.g. OS). This notification should then be
    > forwarded to the Client that owns the resource.
    >
    > In code this looks something:


    Plainly the Resource and Client classes must be declared prior to main(),
    quite apart from any circular dependency issues.

    >
    > int main()
    > {
    > Resource resource; // Define the resource
    > Client client(&resource); // Configure the client to own the
    > resource client.Execute(); // Execute operation, which in turn
    > uses the resource
    >
    > RunEventLoopForever();
    > }
    >
    >
    > class Resource
    > {
    > Client* m_client;
    > public:
    > void SetClient(Client* client)
    > {
    > m_client = client;
    > }
    >
    > void Use()
    > {
    > // Use this resource
    > // DoSomethingInteresting()
    > }
    > void AsyncNotification()
    > {
    > m_client->Notify();
    > }


    This is where your fundamental problem lies. You are calling a member
    function of Client before the client class has been defined. The solution is
    to only declare AsyncNotification here and define it later.

    > };
    >
    > class Client
    > {
    > Resource* m_resource;
    > public:
    > Client(Resource* res) : m_resource(res)
    > {
    > m_resource->SetClient(this);
    > }
    > void Execute()
    > {
    > m_resource->Use();
    > }
    > void Notify()
    > {
    > // Handle notification
    > // m_resource->Whatever()
    > }
    > };
    >
    > What should I do to resolve this issue?
    > Complete redesign? Rather not - I like this simple design (besides it
    > doesn't work...)
    > Introducing something in between to break the dependency? If so -
    > what?
    > Thanks in advamce!
    > /Rob


    The following compiles:

    class Client;

    class Resource
    {
    Client* m_client;
    public:
    void SetClient(Client* client)
    {
    m_client = client;
    }

    void Use()
    {
    // Use this resource
    // DoSomethingInteresting()
    }
    void AsyncNotification();
    };

    class Client
    {
    Resource* m_resource;
    public:
    Client(Resource* res) : m_resource(res)
    {
    m_resource->SetClient(this);
    }
    void Execute()
    {
    m_resource->Use();
    }
    void Notify()
    {
    // Handle notification
    // m_resource->Whatever()
    }
    };

    void Resource::AsyncNotification()
    {
    m_client->Notify();
    }


    int main()
    {
    Resource resource; // Define the resource
    Client client(&resource); // Configure the client to own the resource
    client.Execute(); // Execute operation, which in turn uses the
    resource

    //RunEventLoopForever();
    }


    --
    John Carson
     
    John Carson, Nov 28, 2005
    #3
  4. Rob Clark

    Rob Clark Guest

    Oh so obvious when you have the answer - thank you both guys, Neelesh and
    John!
    /Rob
     
    Rob Clark, Nov 28, 2005
    #4
    1. Advertisements

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. DinkyToy

    circular dependency between jars

    DinkyToy, Apr 7, 2005, in forum: Java
    Replies:
    0
    Views:
    471
    DinkyToy
    Apr 7, 2005
  2. DinkyToy
    Replies:
    1
    Views:
    885
    John McGrath
    Apr 7, 2005
  3. ma740988
    Replies:
    18
    Views:
    2,366
    ma740988
    Jul 28, 2004
  4. Kiuhnm
    Replies:
    16
    Views:
    901
    Jonathan Mcdougall
    Jan 3, 2005
  5. Stefan Seefeld
    Replies:
    1
    Views:
    448
    Michele Simionato
    Jan 19, 2004
  6. James Buchanan
    Replies:
    2
    Views:
    407
    James Buchanan
    Oct 20, 2005
  7. Paul Uiterlinden

    Circular dependency problem

    Paul Uiterlinden, Nov 18, 2006, in forum: VHDL
    Replies:
    2
    Views:
    1,095
    Paul Uiterlinden
    Nov 19, 2006
  8. joshc

    Handling Circular Dependency

    joshc, Jul 16, 2007, in forum: C Programming
    Replies:
    4
    Views:
    456
    joshc
    Jul 16, 2007
Loading...