Domanda

Voglio memorizzare un oggetto di una classe derivata come una proprietà di un altro oggetto.

Il problema per me è conoscere la dimensione dell'oggetto da memorizzare, in quanto può essere qualsiasi classe derivata di una determinata classe di base. Non posso allocare memoria per oggetto la classe base, a destra, in quanto è più piccolo. Suppongo, typeof operatore sarebbe anche solo dare la dimensione della classe base, giusto?

Ecco il mio codice di esempio. Si prega, si vedano i commenti per capire cosa intendo. Mi scusi per l'unoriginality ...

BaseA {};

DerivedA1 : BaseA {public: void property() { cout << 1; }};
DerivedA2 : BaseA {public: void property() { cout << 2; }};
// etc. - several derived classes.

BaseB   // Contains (or links to) an instance of class derived from BaseA.
{
public:
    BaseA * instanceA;

    BaseB (BaseA instanceAX)
    {
        // ??? => How to allocate memory for the object
        // I don't know the real type of?
        instanceA = new BaseA (instanceAX);
    }

    BaseB (BaseA instanceAX) { delete instanceA; }
};

main()
{
    DerivedA1 instanceA1;
    BaseB instanceB (instanceA1);

    // Use "property" regardless of which derived class it belongs to.
    instanceB.instanceA->property();
} 

ho potuto memorizzare un puntatore invece che l'oggetto stesso, sarebbe stato più facile. Ma io non sono sicuro di voler fare affidamento sul chiamante per mantenere l'oggetto di proprietà per la vita di istanza instanceB .

Grazie!

È stato utile?

Soluzione

Bene, prima di tutto, dal momento che si passa nella vostra BaseA per valore, e non con riferimento o un puntatore, vi conosco il tipo; è BaseA. BaseB è stato copiato in un BaseA e che copia BaseA viene inviata alla funzione. Tutti i dati in più in BaseB non è contenuta in instanceAX. Questo si chiama "affettare".

Ma, per rispondere alla tua domanda, è sufficiente non farlo in questo modo. Avete bisogno di una funzione di clone () nella classe BaseB se è destinato a lavorare in questo modo. In alternativa si potrebbe progettare un puntatore intelligente o un altro oggetto che può clonare l'istanza per voi. Se si cerca il mio nome su comp.lang.c ++ con clone () si potrebbe venire attraverso una discussione che ci fosse su quest'ultima idea.

La funzione di clone è, naturalmente, una funzione virtuale che restituisce una copia dell'oggetto corrente:

struct BaseA
{
  virtual BaseA* clone() const = 0;
};

struct BaseB : BaseA
{
  BaseB* clone() const { return new BaseB(*this); }
};

Altri suggerimenti

Vedo due possibilità.

  • Dare BaseA una funzione di membro puramente virtuale, forse chiamato clone, che è responsabile per generare una copia dell'istanza viene chiamato. Poi il costruttore di BaseB potrebbe diventare

    BaseB (BaseA const &instanceAX) { instanceA = instanceAX.clone (); }

  • Si potrebbe anche solo evitare di passare i puntatori prime in tutto e l'uso boost::shared_ptr invece. In questo modo, dal momento che è di riferimento contati, il chiamante non può causare una distruzione prematura della derivazione BaseA che è stato usato per costruire BaseB. Dovreste regolare BaseA * instanceA; a leggere boost::shared_ptr <BaseA> instanceA; Poi il costruttore di BaseB potrebbe essere simile:

    BaseB (boost::shared_ptr <BaseA> a) : instanceA (a) { }

Il problema del primo aproach è che alcuni programmatore client che eredita da, diciamo DerivedA1 possono dimenticare di implementare clone nella sua derivazione. Il problema principale del secondo aproach sarebbe richiedere ogni utente di BaseB per allocare l'oggetto struttura sul mucchio (Poiché si effettua una copia all'interno BaseBs costruttore comunque, almeno il consumo di memoria totale non salirebbe, però)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top