Saya memiliki kelas yang mewakili daftar orang.
class AddressBook
{
public:
AddressBook();
private:
std::vector<People> people;
}
Saya ingin memungkinkan klien untuk beralih pada vektor orang. Pikiran pertama yang saya miliki hanyalah:
std::vector<People> & getPeople { return people; }
Namun, saya tidak ingin membocorkan detail implementasi ke klien . Saya mungkin ingin mempertahankan invarian tertentu ketika vektor dimodifikasi, dan saya kehilangan kendali atas invarian ini ketika saya membocorkan implementasinya.
Apa cara terbaik untuk memungkinkan iterasi tanpa membocorkan internal?
begin()
danend()
berbahaya karena (1) jenis tersebut adalah vektor iterator (kelas) yang mencegah seseorang beralih ke wadah lain seperti aset
. (2) Jika vektornya diubah (misal item yang ditanam atau terhapus), beberapa atau semua iterator vektor bisa saja tidak valid.Jawaban:
memungkinkan iterasi tanpa membocorkan internal adalah persis apa yang dijanjikan pola iterator. Tentu saja itu terutama teori jadi di sini adalah contoh praktis:
Anda memberikan standar
begin
danend
metode, seperti urutan dalam STL dan menerapkannya hanya dengan meneruskan ke metode vektor. Ini tidak membocorkan beberapa detail implementasi yaitu bahwa Anda mengembalikan vektor iterator tetapi tidak ada klien waras yang harus bergantung pada hal itu sehingga itu juga bukan masalah. Saya telah menunjukkan semua kelebihan di sini, tetapi tentu saja Anda bisa mulai dengan hanya menyediakan versi const jika klien tidak dapat mengubah entri People. Menggunakan penamaan standar memiliki manfaat: siapa pun yang membaca kode segera tahu itu memberikan iterasi 'standar' dan karena itu bekerja dengan semua algoritma umum, rentang berdasarkan untuk loop dll.sumber
begin()
danend()
yang hanya meneruskan ke vektorbegin()
danend()
memungkinkan pengguna untuk memodifikasi elemen dalam vektor itu sendiri, mungkin menggunakanstd::sort()
. Bergantung pada invarian apa yang ingin Anda pertahankan, ini mungkin atau mungkin tidak dapat diterima. Menyediakanbegin()
danend()
, bagaimanapun, diperlukan untuk mendukung rentang berbasis C ++ 11 untuk loop.Jika iterasi adalah semua yang Anda butuhkan, maka mungkin pembungkus
std::for_each
sudah cukup:sumber
const
iterasi. Inifor_each()
adalahconst
fungsi anggota. Karenanya, anggotapeople
tersebut dianggap sebagaiconst
. Karenanya,begin()
danend()
akan membebani sebagaiconst
. Karenanya, mereka akan kembaliconst_iterator
kepeople
. Karenanya,f()
akan menerima aPeople const&
. Menuliscbegin()
/ dicend()
sini tidak akan mengubah apa pun, dalam praktiknya, meskipun sebagai pengguna obsesifconst
saya mungkin berpendapat itu masih layak dilakukan, karena (a) mengapa tidak; itu hanya 2 karakter, (b) Saya suka mengatakan apa yang saya maksud, paling tidak denganconst
, (c) itu menjaga agar tidak sengaja menempel di suatu tempat yang bukanconst
, dll.Anda dapat menggunakan idiom jerawat , dan memberikan metode untuk beralih di atas wadah.
Di tajuk:
Dalam sumber:
Dengan cara ini, jika klien Anda menggunakan typedef dari header, mereka tidak akan melihat jenis wadah yang Anda gunakan. Dan detail implementasi sepenuhnya tersembunyi.
sumber
Satu dapat menyediakan fungsi anggota:
Yang memungkinkan akses tanpa memaparkan detail implementasi (seperti kedekatan) dan menggunakannya dalam kelas iterator:
Iterator kemudian dapat dikembalikan oleh buku alamat sebagai berikut:
Anda mungkin perlu menyempurnakan kelas iterator dengan sifat-sifat dll, tetapi saya pikir ini akan melakukan apa yang Anda minta.
sumber
jika Anda ingin implementasi fungsi yang tepat dari std :: vector, gunakan warisan pribadi seperti di bawah ini dan kontrol apa yang terbuka.
Sunting: Ini tidak direkomendasikan jika Anda juga ingin menyembunyikan struktur data internal yaitu std :: vector
sumber
vector
yang, yang Anda tidak pernah ingin gunakan tetapi tetap harus mewarisi?), dan mungkin secara aktif berbahaya (bagaimana jika kelas yang diwarisi dari malas dapat dihapus melalui pointer ke jenis pangkalan di suatu tempat, tetapi [tidak bertanggung jawab] tidak melindungi terhadap penghancuran objek yang diturunkan melalui penunjuk seperti itu, sehingga dengan mudah menghancurkannya adalah UB?)