13

I have converted a scientific simulation platform from Java into C++. I have tried to keep the design as much as possible the same as previous implementation. In java because of the late binding, circular dependencies are resolved at the run time. However, circular dependencies have created a hell of a mess in C++.

  1. Is there an automated tool which analyses and lists the circular includes and references? (Visual Studio 2010 only issues a huge list of nonsense errors).

  2. I have tried to use forward references wherever possible. However in some occasions both classes need functionality of the other class (i.e. call to methods which makes it impossible to use forward reference). These needs exist in Logic and if I radically change the design they will no more represent real world interactions.

    How could we implement two classes which need each other's methods and status? Is it possible to implement them in C++?

Examples:

  • Example 1: I have a class called "World" which creates Objects of the type "Agent". Agent needs to call World methods to get information of its environment. World also needs to iterate through Agents and execute their "run" method and get their status (status updates may possibly be done reverse to solve this section of the problem but not the run method).
  • Example 2: Agents create a collection of their "Intentions". Each Agent needs to iterate through its intentions and run/update/read intention status. Intentions also need to get information about the environment through Agent (if done directly through "World" it will create complex circles again) and also info of the Agent itself.

Below diagram shows a sub-set of classes, and some of their methods and properties:

sub-set of classes, and some of their methods and properties

4

2 回答 2

19

我没有看到前向声明对您不起作用。看起来你需要类似的东西:

世界.h:

#ifndef World_h
#define World_h

class Agent;

class World
{
    World();
    void AddAgent(Agent* agent) { agents.push_back(agent); }
    void RunAgents();
private:
    std::vector<Agent*> agents;
};

#endif

代理.h:

#ifndef Agent_h
#define Agent_h

class World;
class Intention;

class Agent
{
    Agent(World& world_): world(world_) { world.AddAgent(this); }
    status_t Run();
private:
    World& world;
    std::vector<Intention*> intentions;
};

#endif

世界.cc:

#include "World.h"
#include "Agent.h"

void World::RunAgents()
{
    for(std::vector<Agent*>::iterator i = agents.begin(); i != agents.end; ++i)
    {
        Agent& agent(**i);
        status_t stat = agent.Run();
        // do something with stat.
    }
}

// ...

代理.cc:

#include "Agent.h"
#include "World.h"
#include "Intention.h"

// ...
于 2012-06-11T11:27:53.980 回答
3

可以仅使用前向声明来解决问题,但您可能没有将实现与类的声明分开。

如果您需要从类中调用方法,则需要完整类型,这就是您需要包含该文件的原因。您可以将文件包含在cpp(实现文件)中,而不必担心循环依赖。

于 2012-06-11T11:19:44.987 回答