2016-02-15 7 views
5

Próbuję podzielić kod z mojego oprogramowania symulacji C++ do biblioteki, aby można było go używać bardziej elastycznie. Symulacja opiera się na numerze Lattice, składającym się z liczby Node s, które przechowują listy wskaźników do ich Neighbor s. . Chociaż sąsiedzi są również węzły, chciałbym mieć trochę klasy otoki wokół wskaźnika *Node w celu realizacji dodatkowych logika/pola (np bool is_neares_neighbor lub takKtóry wzorzec C++ jest używany w bibliotece, która umożliwia rozszerzanie jej klas?

Moja klasa architektura wygląda więc tak:

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

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

class Neighbor { 
private: 
    Node * _node; 
}; 

tak daleko, tak dobrze. teraz chciałbym moją bibliotekę do obsługi wszystkich logiki związanych kraty, ale nic innego. jednak podczas korzystania z biblioteki w jakimś projekcie, trzy klasy (Lattice, Node, Neighbor) będzie mieć więcej logiki i pól, dlatego użytkownik powinien móc dziedziczyć z tych klas i realizować swój zwyczaj rzeczy, podczas gdy biblioteka nadal obsługuje wszystkie niezbędne logiki związane z siecią.

Jaki jest zalecany sposób na zrobienie tego? Czy szablony są tutaj odpowiednie? W matrycy sytuacji, moja klasa hierarchia będzie wyglądać następująco:

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

Jak widać, zarówno Node i Neighbor trzeba znać typ siebie, która jest okrągła warunek nie mam pojęcia, jak sobie radzić tutaj. Ponadto cała biblioteka musiałaby żyć w plikach nagłówkowych.

Jak sytuacje takie jak te są rozwiązywane w świecie C++ w najbardziej elegancki sposób?

+0

Co to są N i NN? Myślę, że mam rozwiązanie zadanego pytania, chociaż nadal miałbym pewne obawy dotyczące surowego wskaźnika do węzła wewnątrz sąsiada. –

+0

Czy typy węzłów i sąsiadów są naprawdę całkowicie niezależne od siebie? Czy określony typ węzła nie implikuje określonego typu sąsiada? Mogłabym sobie wyobrazić Węzeł i Sąsiad jako abstrakcyjne klasy (interfejsy) i wyprowadzić z nich konkretne węzły i sąsiadów. Ale może źle się spełniłem. –

+0

Hej, dziękuję wam za odpowiedź. @KennyOstrom: N i NN to klasy wywodzące się odpowiednio od 'Node' i' Neighbour', które są dostarczane przez użytkownika. Użytkownik może więc dodawać funkcje i zmienne zarówno do klasy "Węzeł", jak i "Sąsiada". @FrankPuffer: Nie są zależne. Wiele informacji meta może istnieć w związku między dwoma 'węzłami', jak liczniki, i tak dalej. Jest to relacja 1: n, w której można przechowywać dodatkowe informacje o relacji. Jest to jednak prawdopodobnie część, którą mogę łatwo zaoszczędzić, jeśli nie ma innego rozwiązania. Po prostu chcę, żeby była bardzo elastyczna. – janoliver

Odpowiedz

1

Myślę, że chcesz, aby typ szablonu był "jakimś innym typem", którego biblioteka sieci nie zna i nie dba o niego. Zamiast korzystać z funkcji Węzeł użytkownik zamiast tego używa szablonu klasa t_data > dla wszystkich klas.

Powiedziałeś sam, Neighbor jest węzłem, więc powinieneś być w stanie zdefiniować wszystko zgodnie z Node <t_data>.

Powinieneś również rozważyć, w jaki sposób zamierzasz zbudować kratę i jak zwrócisz informacje na jej temat. Oto przykład, w którym zakładam, że tworzysz siatkę, tworząc klasę węzłów, z opcją łączenia ich z istniejącymi węzłami w momencie tworzenia.

#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; 
}; 

ja naprawdę nie rozumiem sąsiad, bo albo jest to węzeł, albo składa się z dwóch węzłów, więc zostawię to jeden sam.

+0

technicznie twoje węzły nie muszą mieć żadnego typu, ale założyłem, że celem tej biblioteki jest praca z jakimś innym typem, i dlatego wspomniałeś szablon –

+0

Cześć Kenny, dziękuję za twoją sugestię. Twoja sugestia wydaje się używać jakiejś dodatkowej struktury danych, która jest po prostu dodawana do klas mojej biblioteki jako członek, podczas gdy sama biblioteka działa z własnymi typami. Wypróbuję to później. Jest nieco mniej elegancki niż myślałem, że mogę to rozwiązać, ponieważ użytkownik jest zmuszony określić taką klasę i nie może korzystać z biblioteki bez niej, ale może to zrobi. – janoliver

+0

Żadna z odpowiedzi nie spełniała moich wymagań bardzo dobrze, dlatego zdecydowałem się nie tworzyć niezależnej biblioteki rzeczy kratowych. Ta odpowiedź byłaby najlepszym wyborem, więc oznaczy to jako poprawną. – janoliver

0

polecam Ci użyć kombinacji wzorca Composite/odwiedzającego:

  • Composite pomoże definiowania hierarchii Lattice/node/sąsiad/Custom_User_Node_Derived klas, które mogą być traktowane jednakowo (niezależnie od treści)
  • Gość pomoże ci przeszukać hierarchię i obudować logikę dla twojej klasy Krata/Węzeł/Sąsiad, a także pozwolić użytkownikowi zdefiniować nowe operacje, których jeszcze nie możesz przewidzieć.

Jest to szczególnie zalecane podejście, gdy chcesz rozszerzyć bibliotekę (lub zestaw klas), na które nie masz kontroli. Z mojego zrozumienia wynika, że ​​jest to jedna z rzeczy, którą chcesz, aby Twój użytkownik mógł.

Powiązane problemy