Implementasi properti di C ++

Halo semuanya! Saat mengimplementasikan proyek, pengembang sering membutuhkan kelas yang hanya berisi bidang dan tidak memiliki fungsi apa pun. Kelas semacam itu berguna untuk menyimpan informasi yang diperlukan dengan manipulasi mereka selanjutnya.

Pendekatan pertama untuk mengimplementasikan kelas-kelas tersebut didasarkan pada penggunaan struktur C. Sebagai kelemahan dari pendekatan ini, semua bidang dapat ditulis dan dibaca, yang tidak selalu baik.

struct person { int id; human type; std::string name; std::string address[5]; bool merried; }; 

Pendekatan kedua didasarkan pada menyembunyikan semua bidang dan menyediakan getter dan setter untuk bidang tersebut. Pendekatan ini jelas digunakan dalam bahasa Jawa. Sebagai keuntungan, kami dapat mengontrol akses ke bidang. Kerugiannya termasuk fakta bahwa kelas menjadi besar, dan getter dan setter tidak membawa beban logis.

 class person { public: void set_id(int id) { this->id = id; } int get_id() const { return id; } void set_merried(bool merried) { this->merried = merried; } bool is_merried() const { return merried; } void set_type(human type) { this->type = type; } human get_type() const { return type; } void set_name(const std::string& name) { this->name = name; } const std::string& get_name() const { return name; } private: int id; human type; std::string name; std::string address[5]; bool merried; }; 

Jika bidang adalah tipe kelas, kadang-kadang Anda perlu mengatur objek dengan nilai, dengan tautan-nilai, dengan tautan-nilai. Dan juga menggunakan const / pengubah volatil.

 class person { public: void set_name(const std::string& name) { this->name = name; } void set_name(std::string&& name) { this->name = std::move(name); } const std::string& get_name() const { return name; } private: int id; human type; std::string name; std::string address[5]; bool merried; }; 

Banyak bahasa mendukung properti sebagai fitur bahasa. Menulis kode menjadi lebih bersih dan lebih dapat diandalkan. Untuk menyederhanakan penulisan getter dan setter, Anda dapat menggunakan makro untuk menghasilkan kode.

 #define SETTER_PRIM(type, name) \ void set_##name(type value) { \ this->name = value; \ } #define GETTER_PRIM(type, name) \ type get_##name() const { \ return name; \ } 

Tetapi menggunakan makro itu berbahaya. Kami mungkin tidak menunjukkan dengan benar tipe (tipe) atau variabel tipe yang salah (nama). Dalam kasus terbaik, kami mendapatkan kesalahan runtime saat menggunakan getter dan setter. Dalam kasus terburuk, kesalahan akan tetap ada.

Saya ingin kami dapat menghasilkan getter dan setter, tetapi pada saat yang sama kami dapat memeriksa kebenaran jenis (tipe), kebenaran jenis dengan variabel (nama) dan bahwa jenisnya sama. Dan ini bisa dilakukan mulai dengan C ++ 11 menggunakan library type_traits standar.

 #define SETTER_PRIM(type, name) \ void set_##name(type value) { \ using T1 = type; \ using T2 = decltype(name); \ static_assert(std::is_fundamental<T1>::value, \ "only primitive types"); \ static_assert(std::is_fundamental<T2>::value, \ "variable must be primitive"); \ static_assert(std::is_same<T1, T2>::value, \ "both types must be same"); \ this->name = value; \ } #define GETTER_PRIM(type, name) \ type get_##name() const { \ using T1 = type; \ using T2 = decltype(name); \ static_assert(std::is_fundamental<T1>::value, \ "only primitive types"); \ static_assert(std::is_fundamental<T2>::value, \ "variable must be primitive"); \ static_assert(std::is_same<T1, T2>::value, \ "both types must be same"); \ return name; \ } 

Dengan menggunakan pendekatan ini, Anda dapat menerapkan getter dan setter untuk semua jenis bidang kelas.

  • tipe primitif
  • jenis objek
  • transfer
  • array
  • pointer
  • tautan

Semua makro untuk getter dan setter diimplementasikan dalam bentuk perpustakaan hanya header. Dengan menghubungkan hanya satu file header, Anda dapat dengan mudah menerapkan kelas tanggal dengan semua getter dan setter yang diperlukan.

 #include "property.hpp" class person { public: person() = default; ~person() = default; SETTER_PRIM(int, id); SETTER_FLAG(bool, merried); SETTER_ENUM(human, type); SETTER_PTR(int, next); SETTER_ARR(std::string, address, 3); SETTER_OBJ_LR(std::string, name); SETTER_OBJ_CLR(std::string, name); SETTER_OBJ_RR(std::string, name); GETTER_PRIM(int, id); GETTER_FLAG(bool, merried); GETTER_ENUM(human, type); GETTER_OBJ_LR(std::string, name); GETTER_OBJ_CLR(std::string, name); GETTER_PTR(int, next); GETTER_ARR(std::string, address); private: int id; human type; std::string name; std::string address[5]; bool merried; int* next; }; 

Kode sumber perpustakaan sumber terbuka dapat dilihat di sini di tautan ini.

Source: https://habr.com/ru/post/id459212/


All Articles