2016-02-15 9 views
5

Sto cercando di dividere il codice dal mio software di simulazione C++ in una libreria, in modo che possa essere utilizzato in modo più flessibile. La simulazione si basa su un Lattice, costituito da un numero di Node s che contengono elenchi di puntatori ai loro Neighbor s. . Anche se i vicini sono nodi anche, mi piacerebbe avere un po 'di classe wrapper intorno al puntatore *Node al fine di attuare ulteriori logiche/campi (ad esempio, o almeno così bool is_neares_neighborQuale pattern C++ usare per una libreria che consente di estendere le sue classi?

mia architettura di classe sembra dunque qualcosa di simile:

class Lattice { 
private: 
    vector<Node> _nodes; 
}; 

class Node { 
private: 
    vector<Neighbor> _neighbors; 
}; 

class Neighbor { 
private: 
    Node * _node; 
}; 

Fin qui, tutto bene. Ora, vorrei la mia libreria per gestire tutta la logica reticolare-correlati, ma nient'altro. Tuttavia, quando si utilizza la libreria in qualche progetto, le tre classi (Lattice, Node, Neighbor) porterà più logica e campi. L'utente dovrebbe quindi essere in grado di ereditare da queste classi e attuare la sua abitudine roba, mentre la libreria gestisce ancora tutta la logica necessaria relativa al reticolo.

Qual è il modo consigliato per farlo? I modelli sono appropriati qui? In una situazione su modelli, la mia gerarchia di classe sarebbe simile a questa:

template<class N> 
class Lattice { 
private: 
    vector<N> _nodes; 
}; 

template<class NN> 
class Node { 
private: 
    vector<NN> _neighbors; 
}; 

template<class N> 
class Neighbor { 
private: 
    N * _node; 
}; 

Come si può vedere, sia bisogno Node e Neighbor di conoscere il tipo di vicenda, che è una condizione circolare non ho idea di come affrontare con qui. Inoltre, l'intera libreria dovrebbe vivere nei file di intestazione.

Come si affrontano situazioni come queste nel mondo C++ nel modo più elegante?

+0

Cosa sono N e NN? Penso di avere una soluzione alla domanda come chiesto, anche se avrei ancora qualche dubbio sul puntatore raw al nodo all'interno del prossimo. –

+0

I tipi di nodi e di vicini sono completamente indipendenti l'uno dall'altro? Non un tipo specifico di Nodo implica un tipo specifico di Neighbor? Immaginerei Node e Neighbor come classi astratte (interfacce) e ricaviamo da loro i nodi concreti e i vicini. Ma forse ho sbagliato il tuo requisito. –

+0

Ehi, grazie per aver risposto entrambi. @KennyOstrom: N e NN sono classi derivate rispettivamente da 'Node' e' Neighbor', che sono fornite dall'utente. Quindi l'utente può aggiungere funzioni e variabili alla classe 'Node' e' Neighbor'. @FrankPuffer: non sono dipendenti. Un sacco di meta-informazioni possono esistere in una relazione tra due 'Node', come contatori e così via. È come una relazione 1: n in cui è possibile memorizzare ulteriori informazioni sulla relazione. Tuttavia, questa è probabilmente la parte che posso risparmiare più facilmente, se non c'è altra soluzione. Voglio solo renderlo molto flessibile. – janoliver

risposta

1

Sto pensando che il tipo di modello sia "un altro tipo" di cui la tua libreria a traliccio non sa o non interessa. Quindi, invece di far derivare l'utente dal nodo, si utilizza invece la classe modello <t_data> per tutte le classi.

Hai detto tu stesso, Neighbor è un nodo, quindi dovresti essere in grado di definire tutto in termini di nodo <t_data>.

Si dovrebbe anche considerare come si costruirà il reticolo e come si restituiranno le informazioni su di esso. Ecco un esempio in cui presumo che tu crei il reticolo avendo la classe reticolo di creare nodi, con l'opzione di collegarli ai nodi esistenti al momento della creazione.

#include <vector> 
#include <memory> 

template<class t_data> 
class SetOfNodes; 

template<class t_data> 
class Node { 
public: 
    Node(t_data value, SetOfNodes neighbors) : _data(value), _neighbors(neighbors) {} 
    is_nearest_neighbor(const Node &other){ 
     // is other in _neighbors? 
     // is other the closest neighbor? 
     return false; 
    } 
private: 
    t_data _data; 
    SetOfNodes _neighbors; 
}; 

template<class t_data> 
class SetOfNodes { 
public: 
    std::vector<std::shared_ptr<Node<t_data>>> _nodes; 
}; 

template<class t_data> 
class Lattice { 
public: 
    SetOfNodes get_all_nodes(); 
    void create_new_node(SetOfNodes neighbors); 
private: 
    SetOfNodes _nodes; 
}; 

Io non capisco Vicino di casa, perché o si tratta di un nodo, o si tratta di due nodi, quindi lascio che uno solo.

+0

tecnicamente i tuoi nodi non devono avere alcun tipo, ma ho pensato che il punto di questa libreria fosse di lavorare con un altro tipo, ed è per questo che hai citato il modello –

+0

Ciao Kenny, grazie per il tuo suggerimento. Il tuo suggerimento sembra utilizzare una sorta di struttura dati aggiuntiva, che viene semplicemente aggiunta alle classi della mia biblioteca come membro, mentre la libreria stessa funziona con i suoi tipi. Ci proverò più tardi. È un po 'meno elegante di quanto pensassi di poter risolvere, in quanto l'utente è costretto a specificare una classe di questo tipo e non può usare la libreria senza di essa, ma forse lo farà. – janoliver

+0

Nessuna delle risposte in realtà corrisponde alle mie esigenze molto bene, motivo per cui ho deciso di non creare una libreria indipendente del materiale reticolare. Questa risposta sarebbe stata la scelta migliore, quindi la contrassegnerò come corretta. – janoliver

0

ti consiglierei di utilizzare una combinazione di composite/Visitor:

  • Composite vi aiuterà definisce una gerarchia di Lattice/node/Neighbour/classes Custom_User_Node_Derived che possono essere trattati in modo uniforme (qualunque sia il contenuto è
  • Il visitatore consente di eseguire la ricerca per indicizzazione della gerarchia e incapsulare la logica per la classe Lattice/Nodo/Neighbor e consente all'utente di definire nuove operazioni che non è ancora possibile prevedere.

È un approccio particolarmente consigliato quando si desidera estendere una libreria (o una serie di classi) su cui non si ha il controllo. Da quanto ho capito, è una delle cose che vuoi che il tuo utente sia in grado di fare.

Problemi correlati