2012-06-11 15 views
12

He convertido una plataforma de simulación científica de Java en C++. Intenté mantener el diseño tanto como sea posible igual a la implementación anterior. En Java debido a la vinculación tardía, las dependencias circulares se resuelven en el tiempo de ejecución. Sin embargo, las dependencias circulares han creado un desorden en C++.C++, dos clases con necesidades mutuas

  1. ¿Existe una herramienta automatizada que analiza y enumera las inclusiones y referencias circulares? (Visual Studio 2010 solo emite una gran lista de errores sin sentido).

  2. He intentado utilizar referencias avanzadas siempre que sea posible. Sin embargo, en algunas ocasiones ambas clases necesitan funcionalidad de la otra clase (es decir, llamada a métodos que hace que sea imposible usar la referencia directa). Estas necesidades existen en Logic y si cambio radicalmente el diseño, ya no representarán interacciones del mundo real.

    ¿Cómo podríamos implementar dos clases que necesitan los métodos y el estado de los demás? ¿Es posible implementarlos en C++?

Ejemplos:

  • Ejemplo 1: Tengo una clase llamada "World", que crea los objetos del tipo "agente". El agente necesita llamar a los métodos mundiales para obtener información de su entorno. World también necesita iterar a través de Agentes y ejecutar su método "ejecutar" y obtener su estado (es posible que las actualizaciones de estado se realicen en sentido inverso para resolver esta sección del problema, pero no el método de ejecución).
  • Ejemplo 2: Los agentes crean una colección de sus "Intenciones". Cada agente necesita repetir sus intenciones y ejecutar/actualizar/leer el estado de intención. Las intenciones también necesitan obtener información sobre el entorno a través del Agente (si se hace directamente a través de "Mundo" creará círculos complejos nuevamente) y también la información del Agente mismo.

A continuación diagrama muestra un sub-conjunto de clases, y algunos de sus métodos y propiedades:

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

+0

Si tiene problemas con los errores, siempre puede publicar una pregunta que contenga esos errores (literalmente, por favor) y es probable que alguien pueda ayudarlo. Además, esos errores pueden ser absurdos para usted, pero no para otra persona. También es muy difícil responder preguntas sin ver algún código, y para esto te recomiendo que leas http://sscce.org/. –

+0

Joachim, son el tipo de errores que se generan en casos de dependencia circular. Las clases no pueden ser identificadas. 'código' 1> e: \ programación \ cprojt \ actiondb11 \ actiondb \ base \ world.h (35): error C2143: error de sintaxis: falta ',' antes '*' 1> e: \ programming \ cprojt \ actiondb11 \ actiondb \ base \ world.h (36): error C2061: error de sintaxis: identificador 'Agente' 1> e: \ programming \ cprojt \ actiondb11 \ actiondb \ base \ world.h (50): error C2065: ' Agente ': identificador no declarado – wmac

+1

Publicar el código es mucho más útil que publicar los errores. Publicar * ambos * es lo mejor. –

Respuesta

17

No veo cómo las declaraciones avanzadas no funcionan para usted. Parece que necesita algo así como:

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

// ... 

agente.CC:

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

// ... 
+1

Probaré las referencias futuras nuevamente con los archivos de inclusión en la parte superior de los archivos cpp. Supongo que con suerte resolvería los problemas. – wmac

+3

Aunque el idioma no lo requiere, es una buena práctica colocar todas las inclusiones al principio del archivo para que alguien que lea el código pueda conocer rápidamente sus dependencias. –

+1

¿Existe una solución si no solo tiene referencias, sino instancias reales de tipo A en Tipo B y viceversa? Aparece un error de "tipo incompleto" del compilador, lo cual tiene sentido. Pero, ¿hay alguna forma de evitarlo? –

3

Usted puede resolver el problema con sólo hacia adelante declaraciones, pero es probable que dejase' t separe la implementación de la declaración de la clase.

Si necesita llamar a los métodos de la clase, se necesita un tipo completo, por lo que debe incluir el archivo. Puede incluir el archivo en cpp (archivo de implementación) sin preocuparse por las dependencias circulares.

+0

Gracias Luchian. Mi implementación es separada pero no moví incluye a los archivos cpp junto con las referencias directas. – wmac

Cuestiones relacionadas