Come creare una matrice di oggetti di class con modelli?

Non ho fatto alcuna programmazione in C ++ per un po ‘di tempo e ho deciso che avrei fatto un po’ di confusione nel mio tempo libero, quindi ho deciso di scrivermi un piccolo programma di database solo per divertimento e ho problemi con la creazione una serie di oggetti di class con modelli.

Quello che ho è questa class che voglio usare per rappresentare un campo in un record del database.

template  class Field { private: T field; int field_type; public: // ... }; 

E voglio usare una matrice di quella class per rappresentare un record in un database usando questa class.

 class Database_Record { private: int id; Field record[]; public: Database_Record(int); Database_Record(int, Field[]); ~Database_Record(); }; 

Il punto in cui sono bloccato è la creazione dell’array nella class Database_Record poiché si tratta di una matrice di oggetti di class basati su modelli con ogni elemento che potrebbe essere di un tipo diverso e non sono sicuro di come sia necessario dichiarare l’array a causa di ciò. È quello che sto cercando di fare anche io o lo sto facendo nel modo sbagliato? Qualsiasi aiuto sarebbe molto apprezzato.

Field e il Field sono due tipi completamente diversi. Per trattarli in un vettore devi generarli da qualche parte. Puoi scrivere AbstractField e

 struct AbstractField{ virtual ~AbstractField() = 0; }; template class Field: public AbstractField{ private: T field; public: const static int field_type; public: virtual ~Field(){} }; class Database_Record{ std::vector record; public: ~Database_Record(){ //delete all AbstractFields in vector } }; 

e quindi mantieni un vector di AbstractField . usa anche il vector invece di [] . Usa AbstractField* invece di AbstractField e scrivi almeno un puro virtuale in AbstractField .

puoi rendere il distruttore di AbstractField puro virtuale. e non dimenticare di cancellare tutti i campi AbstractField . in ~Database_Record()

Stai andando nella direzione sbagliata.

I modelli sono usati per creare tipi distinti: std::vector e std::vector sono distinti nello stesso modo (e tanto) di int e float .

Anche la tua syntax è sbagliata; per creare un array dinamico devi inserire il seguente membro nel tuo Database_Record :

  std::vector record; // if this was possible; however, it's not 

Per mettere diversi oggetti di tipo distinto in un singolo array, dovrebbero avere una class base comune.

Per creare una serie di tipi diversi è necessaria una class base per gli oggetti e la matrice sarà una matrice di puntatori a quella class base. Quindi, ad esempio,

 class Field { public: virtual ~Field() {} virtual std::string toString() const = 0; // and possibly other interface functions... }; template  FieldImpl : public Field { public: virtual std::string toString() const { std::stringstream ss; ss << val; return ss.str(); } // implementation of possibly other interface functions private: T val; } 

saranno i tipi che ti servono. L'array sarà quindi qualcosa di simile

 std::vector> my_array; 

Puoi quindi fare cose con il tuo array usando le funzioni dell'interfaccia, ad es

 my_array[i]->toString(); 

Considerare ogni istanza con un argomento modello diverso per essere una class diversa. È necessario memorizzare una class specifica (ad es. Field ) oppure è necessario disporre di una class base non basata su modelli che è ansible memorizzare in un elenco.

Puoi fare qualcosa come questo –

 template  class Field { private: T field; int field_Type; }; template  class Database_record { private: int id; std::vector > record_; }; 

Stai facendo modelli sbagliati. L’istanziazione di modelli di classi con tipi diversi restituirà due tipi diversi di dimensioni diverse, il che rende imansible memorizzarli in un array.

Se vuoi trattare diversi tipi in modo uniforms, usa l’ereditarietà. E quando usi l’ereditarietà, non usare matrici semplici, ma vector o std::array .

C’è anche un sacco di cose strane nel tuo codice: Perché memorizzare un fieldTypeId quando è noto staticamente? Immagino sia correlato al tipo T che stai usando come parametro template. Esternare il meccanismo attraverso specializzazioni parziali:

 template struct fieldTypeId; template<> struct fieldTypeId { const static int value = 0; }; // etc.... 

Se ho torto completamente e sai davvero cosa stai facendo: usa il tipo cancellato da any tipo (es. Boost.Any ).

Come è stato detto prima, i modelli C ++ non funzionano così.

Allo stesso modo, l’utilizzo dell’ereditarietà e dei vettori di puntatori non è adatto per implementazioni di record DB a causa di limiti di prestazioni.

Fai un passo indietro e guarda il problema in un modo più astratto. Come ho capito dal tuo codice, l’intento è di confezionare un numero arbitrario di campi di tipi diversi in un blocco di memoria continua. schematicamente:

 struct DBRecord { Type1 f1; Type2 f2; Type3 f3; Type4 f4; // etc... } 

È ansible ottenere questo risultato con un costrutto un po ‘brutto ma pratico costituito da una dichiarazione modello astratta e diverse specializzazioni.

La dichiarazione sarebbe simile a questa:

 template < typename T1, typename T2 = void, typename T3 = void, typename T4 = void, typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void, typename T9 = void, typename T10 = void > struct DBRecord; 

Ovviamente limita un numero massimo di campi ad un numero specifico. Se hai bisogno di un numero veramente arbitrario di campi devi passare al paradigma orientato alle colonne.

Quindi, le specializzazioni parziali dovrebbero dichiarare l’anatomia delle strutture per ciascun numero di argomenti da 1 a 10:

 template < typename T1 > struct DBRecord  { int id; T1 f1; DBRecord(int ID, T1 F1) {/*...*/}; }; template < typename T1, typename T2 > struct DBRecord  { int id; T1 f1; T2 f2; DBRecord(int ID, T1 F1, T2 F2) {/*...*/}; }; // etc... 

Ora, puoi allocare tabelle come matrici di record di determinati tipi in una new[] chiamata, se lo desideri. E di solito non ti preoccupi della distruzione di ogni campo, dato che hai memoria gratuita dell’intera struttura.

Le macro possono aiutare a rendere una dichiarazione di tali specializzazioni un po ‘più compatta.