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. Advertising

  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. Advertising

  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. Advertising

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. Roedy Green

    Re: Circular dependency

    Roedy Green, Aug 19, 2003, in forum: Java
    Replies:
    0
    Views:
    385
    Roedy Green
    Aug 19, 2003
  2. John Hodgson

    Re: Circular dependency

    John Hodgson, Aug 20, 2003, in forum: Java
    Replies:
    0
    Views:
    402
    John Hodgson
    Aug 20, 2003
  3. Andrew Cowper

    Re: Circular dependency

    Andrew Cowper, Aug 20, 2003, in forum: Java
    Replies:
    0
    Views:
    381
    Andrew Cowper
    Aug 20, 2003
  4. John C. Bollinger

    Re: Circular dependency

    John C. Bollinger, Aug 20, 2003, in forum: Java
    Replies:
    0
    Views:
    389
    John C. Bollinger
    Aug 20, 2003
  5. Kiuhnm
    Replies:
    16
    Views:
    722
    Jonathan Mcdougall
    Jan 3, 2005
Loading...

Share This Page