gerarchia di classi con sottoclassi strutturalmente diverse

2

Voglio implementare un livello di protocollo che si trova sopra lo stack TCP / IP. Esiste un insieme limitato di PDU che possono essere inviati e per ciascuna PDU esiste una classe che la rappresenta in una forma strutturata. Ogni classe ha una funzione per serializzare i dati strutturati in un modulo pronto per la trasmissione e deserializzarli in una forma strutturata.

Queste PDU sono strutturalmente molto diverse, ad esempio:

struct a_associate_ac : property 
{
      a_associate_ac() = default;
      void from_pdu(std::vector<unsigned char> pdu) override;
      std::vector<unsigned char> make_pdu() const override;
      pdu::TYPE type() const override;


      std::string called_ae;
      std::string calling_ae;
      std::string application_context;

      struct presentation_context
      {
            enum class RESULT
            {
               ACCEPTANCE = 0x00, USER_REJEC = 0x01,
               PROV_REJEC_NO_REASON = 0x02,
               ABSTR_CONT_NOT_SUPP = 0x03,
               TRANFS_SYNT_NOT_SUPP = 0x04
            };

            presentation_context() = default;
            unsigned char id;
            RESULT result_;
            std::string transfer_syntax;
      };

      std::vector<presentation_context> pres_contexts;
      std::size_t max_message_length;
};

rispetto a:

struct a_associate_rj: property
{
      a_associate_rj() = default;
      void from_pdu(std::vector<unsigned char> pdu) override;
      std::vector<unsigned char> make_pdu() const override ;
      pdu::TYPE type() const override;

      enum class SOURCE : unsigned char
      {
         UL_SERVICE_USER = 0x01, UL_SERVICE_PROV_ACSE = 0x02,
         UL_SERVICE_PROV_PRESREL = 0x03
      };
      enum class REASON : unsigned char
      {
         NOT_SPECIFIED = 0x01, APPL_CONT_NOT_SUPP = 0x02, CALLING_AE_NOT_RECOG = 0x03,
         CALLED_AE_NOT_RECOG = 0x07
      };

      REASON reason_;
      SOURCE source_;
};

Tutte queste classi ereditano da una proprietà di superclasse astratta. la proprietà viene utilizzata dalla classe layer, che implementa il protocollo, in due funzioni membro:

void send(const property* p);
std::unique_ptr<const property> receive();

Questo significa che se l'utente della classe layer riceve una proprietà e vuole accedere ai suoi membri, deve verificare quale tipo di proprietà è stata ricevuta usando property::type() e downcast a quel tipo, che trovo piuttosto irritante.

Cosa si può fare per risolvere questo problema?

    
posta Marius Herzog 30.08.2014 - 15:59
fonte

1 risposta

1

Dipende un po 'da quello che stai facendo con queste proprietà, ma uno schema che aggirerebbe il casting esplicito sarebbe doppia spedizione o "visitatore". È un modello comune che viene utilizzato per operare sugli alberi, ma pensa che potrebbe soddisfare le tue necessità. In c ++ l'unico svantaggio è che esiste un punto in cui potrebbe essere necessario fare riferimento a tutte le proprietà in modo esplicito. Questo è ciò che potrebbe sembrare uno stub per questo:

class Property {
    virtual void visit(Visitor *visitor) = 0;
}

class SpecificPropertyA {
     void visit(Visitor *visitor) {
        visitor->handle(this);
    }
}

class Visitor {

    void handle(Property *)  {
        // This is catch all and will deal with not implemented handle functions
    }

    void handle(SpecificPropertyA* property) {
        // Do the specific work here
    }

    void handle(SpecificPropertyB* property) {
        // Do the specfic work here
    }
} 

Puoi avere tanti tipi diversi di visitatori che desideri, derivando dall'interfaccia del visitatore. Per esempio. implementando un logger in contrasto con un processore.

Si noti che questo è solo un modo per separare le funzionalità dai dati, a seconda del problema che si sta tentando di risolvere potrebbe essere più semplice fornire ciascuna delle proprietà con una funzione process() che viene chiamata e fa l'appropriato lavora senza dover esporre il tipo.

    
risposta data 30.08.2014 - 16:49
fonte