Sto per progettare un'API in cui esistono due classi: una classe data/di calcolo e un contenitore per questa classe. Il container, tuttavia, non è semplicemente un contenitore stupido, ma porta anche informazioni sulla collezione nel suo complesso che va oltre le solite cose che possono essere implementate con gli iteratori.Funzioni di Accessor per contenitori con std :: unique_ptr
Così, il contenitore avvolge fondamentalmente un std::vector
, aggiunge alcuni attributi precalcolate, funzioni di utilità, ecc Che le API della classe contenitore dovrebbe anche contenere è
- Un metodo per aggiungere le istanze dei dati/calc classe,
- metodi di accesso.
non mi vogliono semplicemente aprire la std::vector
al pubblico, perché l'aggiunta di una nuova classe di dati/calc al contenitore fa sì che il ri-calcolo di una serie di attributi della classe collezione. Tuttavia, desidero fornire un metodo accessor uguale ai metodi accessor del contenitore STL at()
e operator []
.
Inizialmente, ho aggiunto un attributo privato del tipo std::vector<std::unique_ptr<DataClass>>
. Esiste un metodo addDataObject(DataObject *d)
che racchiude l'oggetto in un unique_ptr
e aggiorna le statistiche.
Il problema, tuttavia, viene fornito con i metodi di accesso: Quale sarebbe il loro tipo di ritorno?
- Semplicemente tornando
std::unique_ptr<DataClass> &
non sembra essere un progetto API pulito: l'utente delle API non ha bisogno di sapere che uso puntatori intelligenti. (Vedi anche la presentazione di Herb Sutter su C++ 11) - Tornando
DataClass *&
non è possibile, soprattutto non peroperator []
, perché posso accedere solo il puntatore grezza di unstd::unique_ptr
usando il metodo del puntatore intelligenteget()
, il che non mi dà un riferimento. - Il ritorno di
DataClass &
non sembra avere senso, soprattutto quando sto memorizzando i puntatori (allocazione heap vs. stack). - Il ripristino di
DataClass *
viola il principio di minima sorpresa, perché se un metodo è denominato nel senso dei metodi accessor del contenitore STL, ci si aspetterebbe che restituisca un riferimento, in particolare peroperator []
.
titolo di esempio, questo sarebbe un esempio semplificato:
class DataClass
{
Container *m_parent;
/* ... other member attributes/parameters ... */
public:
/* A method that calculates something based on the attributes: */
double someComplicatedCalculation(const double &input);
};
class Container
{
std::vector<std::unique_ptr<DataClass>> m_collection;
/* more attributes: maintenance info, precomputed values, etc. */
public:
void addDataObject(DataClass *d);
/* What would the right return type be? */
DataClass *&at(const int &index);
const DataClass *&at(const int &index) const;
DataClass *&operator [](const int &index);
const DataClass *&operator [](const int &index) const;
};
Qual è il significato di unique_ptr in questo contesto? Vuoi che venga invalidato quando viene chiamato? Vuoi che esistano due copie di unique_ptr? Quindi non è molto unico. –
C'è un motivo per cui i puntatori del negozio nel tuo vettore piuttosto che gli oggetti stessi? – Galik
@Galik OP ottiene gli oggetti con il puntatore e assume la proprietà - perché copiare o spostare un oggetto quando è sufficiente copiare il puntatore? – Barry