13

科学シミュレーションプラットフォームをJavaからC++に変換しました。以前の実装と可能な限り同じデザインを維持するように努めました。Javaでは、バインディングが遅いため、循環依存関係は実行時に解決されます。ただし、循環依存関係により、C++では混乱が生じています。

  1. サーキュラーインクルードとリファレンスを分析して一覧表示する自動化ツールはありますか?(Visual Studio 2010は、ナンセンスエラーの膨大なリストのみを発行します)。

  2. 可能な限り前方参照を使用しようとしました。ただし、場合によっては、両方のクラスが他のクラスの機能を必要とします(つまり、前方参照を使用できないようにするメソッドの呼び出し)。これらのニーズはLogicに存在し、設計を根本的に変更すると、現実世界の相互作用を表すことはなくなります。

    お互いのメソッドとステータスを必要とする2つのクラスをどのように実装できますか?それらをC++で実装することは可能ですか?

例:

  • 例1:「Agent」タイプのオブジェクトを作成する「World」というクラスがあります。エージェントは、その環境の情報を取得するためにWorldメソッドを呼び出す必要があります。Worldはまた、エージェントを反復処理し、「run」メソッドを実行してステータスを取得する必要があります(ステータスの更新は、問題のこのセクションを解決するために逆に行われる可能性がありますが、runメソッドは解決されません)。
  • 例2:エージェントは「意図」のコレクションを作成します。各エージェントは、その意図と実行/更新/読み取り意図のステータスを反復処理する必要があります。また、エージェントを介して環境に関する情報を取得する必要があります(「ワールド」を介して直接実行すると、複雑な円が再び作成されます)。また、エージェント自体の情報も取得する必要があります。

次の図は、クラスのサブセットと、それらのメソッドおよびプロパティの一部を示しています。

クラスのサブセット、およびそれらのメソッドとプロパティの一部

4

2 に答える 2

19

前方宣言がどのように機能していないのかわかりません。次のようなものが必要なようです。

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

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

World.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.
    }
}

// ...

Agent.cc:

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

// ...
于 2012-06-11T11:27:53.980 に答える
3

前方宣言だけで問題を解決できますが、おそらく実装をクラスの宣言から分離していません。

クラスからメソッドを呼び出す必要がある場合は、完全な型が必要です。そのため、ファイルを含める必要があります。cpp循環依存関係を気にすることなく、ファイルを(実装ファイル)に含めることができます。

于 2012-06-11T11:19:44.987 に答える